MainPipe.scala 64.1 KB
Newer Older
L
Lemover 已提交
1 2
/***************************************************************************************
* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
Y
Yinan Xu 已提交
3
* Copyright (c) 2020-2021 Peng Cheng Laboratory
L
Lemover 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16
*
* XiangShan is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*          http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/

A
Allen 已提交
17 18
package xiangshan.cache

19
import chipsalliance.rocketchip.config.Parameters
A
Allen 已提交
20 21
import chisel3._
import chisel3.util._
22 23 24
import freechips.rocketchip.tilelink.ClientStates._
import freechips.rocketchip.tilelink.MemoryOpCategories._
import freechips.rocketchip.tilelink.TLPermissions._
A
Allen 已提交
25
import freechips.rocketchip.tilelink.{ClientMetadata, ClientStates, TLPermissions}
Z
zhanglinjuan 已提交
26
import utils._
27
import xiangshan.L1CacheErrorInfo
A
Allen 已提交
28

Z
zhanglinjuan 已提交
29 30
class MainPipeReq(implicit p: Parameters) extends DCacheBundle {
  val miss = Bool() // only amo miss will refill in main pipe
A
Allen 已提交
31 32
  val miss_id = UInt(log2Up(cfg.nMissEntries).W)
  val miss_param = UInt(TLPermissions.bdWidth.W)
33
  val miss_dirty = Bool()
34
  val miss_way_en = UInt(DCacheWays.W)
A
Allen 已提交
35 36 37

  val probe = Bool()
  val probe_param = UInt(TLPermissions.bdWidth.W)
38
  val probe_need_data = Bool()
A
Allen 已提交
39 40

  // request info
Z
zhanglinjuan 已提交
41
  // reqs from Store, AMO use this
A
Allen 已提交
42 43
  // probe does not use this
  val source = UInt(sourceTypeWidth.W)
Z
zhanglinjuan 已提交
44
  val cmd = UInt(M_SZ.W)
45 46 47
  // if dcache size > 32KB, vaddr is also needed for store
  // vaddr is used to get extra index bits
  val vaddr  = UInt(VAddrBits.W)
A
Allen 已提交
48 49 50 51
  // must be aligned to block
  val addr   = UInt(PAddrBits.W)

  // store
Z
zhanglinjuan 已提交
52 53
  val store_data = UInt((cfg.blockBytes * 8).W)
  val store_mask = UInt(cfg.blockBytes.W)
A
Allen 已提交
54 55 56 57

  // which word does amo work on?
  val word_idx = UInt(log2Up(cfg.blockBytes * 8 / DataBits).W)
  val amo_data   = UInt(DataBits.W)
Z
zhanglinjuan 已提交
58 59
  val amo_mask   = UInt((DataBits / 8).W)

60 61 62
  // error
  val error = Bool()

63 64 65 66
  // replace
  val replace = Bool()
  val replace_way_en = UInt(DCacheWays.W)

Z
zhanglinjuan 已提交
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
  val id = UInt(reqIdWidth.W)

  def isLoad: Bool = source === LOAD_SOURCE.U
  def isStore: Bool = source === STORE_SOURCE.U
  def isAMO: Bool = source === AMO_SOURCE.U

  def convertStoreReq(store: DCacheLineReq): MainPipeReq = {
    val req = Wire(new MainPipeReq)
    req := DontCare
    req.miss := false.B
    req.miss_dirty := false.B
    req.probe := false.B
    req.probe_need_data := false.B
    req.source := STORE_SOURCE.U
    req.cmd := store.cmd
    req.addr := store.addr
    req.vaddr := store.vaddr
    req.store_data := store.data
    req.store_mask := store.mask
86
    req.replace := false.B
87
    req.error := false.B
Z
zhanglinjuan 已提交
88 89
    req.id := store.id
    req
A
Allen 已提交
90 91 92
  }
}

93 94 95 96 97
class MainPipeStatus(implicit p: Parameters) extends DCacheBundle {
  val set = UInt(idxBits.W)
  val way_en = UInt(nWays.W)
}

98
class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents {
99 100 101 102 103 104 105 106 107 108
  val nDupDataWriteReady = 4
  val nDupTagWriteReady = 4
  val nDupStatus = nDupDataWriteReady + nDupTagWriteReady
  val nDupWbReady = 4

  val dataWritePort = 0
  val metaWritePort = 1
  val tagWritePort = 2
  val errWritePort = 3

Z
zhanglinjuan 已提交
109 110 111 112
  val io = IO(new Bundle() {
    // probe queue
    val probe_req = Flipped(DecoupledIO(new MainPipeReq))
    // store miss go to miss queue
W
William Wang 已提交
113
    val miss_req = DecoupledIO(new MissReq)
Z
zhanglinjuan 已提交
114 115 116 117 118 119 120 121
    // store buffer
    val store_req = Flipped(DecoupledIO(new DCacheLineReq))
    val store_replay_resp = ValidIO(new DCacheLineResp)
    val store_hit_resp = ValidIO(new DCacheLineResp)
    val release_update = ValidIO(new ReleaseUpdate)
    // atmoics
    val atomic_req = Flipped(DecoupledIO(new MainPipeReq))
    val atomic_resp = ValidIO(new AtomicsResp)
122 123 124
    // replace
    val replace_req = Flipped(DecoupledIO(new MainPipeReq))
    val replace_resp = ValidIO(UInt(log2Up(cfg.nMissEntries).W))
Z
zhanglinjuan 已提交
125 126
    // write-back queue
    val wb = DecoupledIO(new WritebackReq)
127
    val wb_ready_dup = Vec(nDupWbReady, Input(Bool()))
Z
zhanglinjuan 已提交
128

129
    val data_read_intend = Output(Bool())
Z
zhanglinjuan 已提交
130 131
    val data_read = DecoupledIO(new L1BankedDataReadLineReq)
    val data_resp = Input(Vec(DCacheBanks, new L1BankedDataReadResult()))
132
    val readline_error_delayed = Input(Bool())
Z
zhanglinjuan 已提交
133
    val data_write = DecoupledIO(new L1BankedDataWriteReq)
134
    val data_write_ready_dup = Vec(nDupDataWriteReady, Input(Bool()))
Z
zhanglinjuan 已提交
135 136

    val meta_read = DecoupledIO(new MetaReadReq)
137
    val meta_resp = Input(Vec(nWays, new Meta))
Z
zhanglinjuan 已提交
138
    val meta_write = DecoupledIO(new MetaWriteReq)
139 140
    val error_flag_resp = Input(Vec(nWays, Bool()))
    val error_flag_write = DecoupledIO(new ErrorWriteReq)
Z
zhanglinjuan 已提交
141 142

    val tag_read = DecoupledIO(new TagReadReq)
143
    val tag_resp = Input(Vec(nWays, UInt(encTagBits.W)))
Z
zhanglinjuan 已提交
144
    val tag_write = DecoupledIO(new TagWriteReq)
145
    val tag_write_ready_dup = Vec(nDupTagWriteReady, Input(Bool()))
146
    val tag_write_intend = Output(new Bool())
147

Z
zhanglinjuan 已提交
148 149 150 151 152 153 154
    // update state vec in replacement algo
    val replace_access = ValidIO(new ReplacementAccessBundle)
    // find the way to be replaced
    val replace_way = new ReplacementWayReqIO

    val status = new Bundle() {
      val s0_set = ValidIO(UInt(idxBits.W))
155
      val s1, s2, s3 = ValidIO(new MainPipeStatus)
Z
zhanglinjuan 已提交
156
    }
157 158 159
    val status_dup = Vec(nDupStatus, new Bundle() {
      val s1, s2, s3 = ValidIO(new MainPipeStatus)
    })
160 161 162

    // lrsc locked block should block probe
    val lrsc_locked_block = Output(Valid(UInt(PAddrBits.W)))
Z
zhanglinjuan 已提交
163
    val invalid_resv_set = Input(Bool())
W
William Wang 已提交
164
    val update_resv_set = Output(Bool())
165
    val block_lr = Output(Bool())
166 167 168

    // ecc error
    val error = Output(new L1CacheErrorInfo())
169 170
  })

Z
zhanglinjuan 已提交
171 172 173
  // meta array is made of regs, so meta write or read should always be ready
  assert(RegNext(io.meta_read.ready))
  assert(RegNext(io.meta_write.ready))
174

Z
zhanglinjuan 已提交
175 176
  val s1_s0_set_conflict, s2_s0_set_conlict, s3_s0_set_conflict = Wire(Bool())
  val set_conflict = s1_s0_set_conflict || s2_s0_set_conlict || s3_s0_set_conflict
Z
zhanglinjuan 已提交
177 178 179 180
  // check sbuffer store req set_conflict in parallel with req arbiter
  // it will speed up the generation of store_req.ready, which is in crit. path
  val s1_s0_set_conflict_store, s2_s0_set_conlict_store, s3_s0_set_conflict_store = Wire(Bool())
  val store_set_conflict = s1_s0_set_conflict_store || s2_s0_set_conlict_store || s3_s0_set_conflict_store
181 182
  val s1_ready, s2_ready, s3_ready = Wire(Bool())

Z
zhanglinjuan 已提交
183 184 185 186 187 188 189 190
  // convert store req to main pipe req, and select a req from store and probe
  val store_req = Wire(DecoupledIO(new MainPipeReq))
  store_req.bits := (new MainPipeReq).convertStoreReq(io.store_req.bits)
  store_req.valid := io.store_req.valid
  io.store_req.ready := store_req.ready

  // s0: read meta and tag
  val req = Wire(DecoupledIO(new MainPipeReq))
191 192 193
  arbiter(
    in = Seq(
      io.probe_req,
W
William Wang 已提交
194
      io.replace_req,
Z
zhanglinjuan 已提交
195
      store_req, // Note: store_req.ready is now manually assigned for better timing
W
William Wang 已提交
196
      io.atomic_req
197 198 199 200
    ),
    out = req,
    name = Some("main_pipe_req")
  )
Z
zhanglinjuan 已提交
201 202 203 204 205 206

  val store_idx = get_idx(io.store_req.bits.vaddr)
  // manually assign store_req.ready for better timing
  // now store_req set conflict check is done in parallel with req arbiter
  store_req.ready := io.meta_read.ready && io.tag_read.ready && s1_ready && !store_set_conflict &&
    !io.probe_req.valid && !io.replace_req.valid
Z
zhanglinjuan 已提交
207 208
  val s0_req = req.bits
  val s0_idx = get_idx(s0_req.vaddr)
209
  val s0_need_tag = io.tag_read.valid
Z
zhanglinjuan 已提交
210 211
  val s0_can_go = io.meta_read.ready && io.tag_read.ready && s1_ready && !set_conflict
  val s0_fire = req.valid && s0_can_go
212

213 214 215
  val bank_write = VecInit((0 until DCacheBanks).map(i => get_mask_of_bank(i, s0_req.store_mask).orR)).asUInt
  val bank_full_write = VecInit((0 until DCacheBanks).map(i => get_mask_of_bank(i, s0_req.store_mask).andR)).asUInt
  val banks_full_overwrite = bank_full_write.andR
216

217 218 219
  val banked_store_rmask = bank_write & ~bank_full_write
  val banked_full_rmask = ~0.U(DCacheBanks.W)
  val banked_none_rmask = 0.U(DCacheBanks.W)
220

Z
zhanglinjuan 已提交
221
  val store_need_data = !s0_req.probe && s0_req.isStore && banked_store_rmask.orR
222
  val probe_need_data = s0_req.probe
Z
zhanglinjuan 已提交
223 224
  val amo_need_data = !s0_req.probe && s0_req.isAMO
  val miss_need_data = s0_req.miss
225
  val replace_need_data = s0_req.replace
Y
Yinan Xu 已提交
226

227
  val banked_need_data = store_need_data || probe_need_data || amo_need_data || miss_need_data || replace_need_data
228

Z
zhanglinjuan 已提交
229
  val s0_banked_rmask = Mux(store_need_data, banked_store_rmask,
230
    Mux(probe_need_data || amo_need_data || miss_need_data || replace_need_data,
Y
Yinan Xu 已提交
231
      banked_full_rmask,
232 233
      banked_none_rmask
    ))
234 235

  // generate wmask here and use it in stage 2
236 237 238
  val banked_store_wmask = bank_write
  val banked_full_wmask = ~0.U(DCacheBanks.W)
  val banked_none_wmask = 0.U(DCacheBanks.W)
239

Z
zhanglinjuan 已提交
240
  // s1: read data
241
  val s1_valid = RegInit(false.B)
242
  val s1_need_data = RegEnable(banked_need_data, s0_fire)
243
  val s1_req = RegEnable(s0_req, s0_fire)
244 245
  val s1_banked_rmask = RegEnable(s0_banked_rmask, s0_fire)
  val s1_banked_store_wmask = RegEnable(banked_store_wmask, s0_fire)
246
  val s1_need_tag = RegEnable(s0_need_tag, s0_fire)
Z
zhanglinjuan 已提交
247 248 249
  val s1_can_go = s2_ready && (io.data_read.ready || !s1_need_data)
  val s1_fire = s1_valid && s1_can_go
  val s1_idx = get_idx(s1_req.vaddr)
Z
zhanglinjuan 已提交
250 251 252 253 254

  // duplicate regs to reduce fanout
  val s1_valid_dup = RegInit(VecInit(Seq.fill(6)(false.B)))
  val s1_req_vaddr_dup_for_data_read = RegEnable(s0_req.vaddr, s0_fire)
  val s1_idx_dup_for_replace_way = RegEnable(get_idx(s0_req.vaddr), s0_fire)
255 256

  val s1_valid_dup_for_status = RegInit(VecInit(Seq.fill(nDupStatus)(false.B)))
Z
zhanglinjuan 已提交
257

258 259
  when (s0_fire) {
    s1_valid := true.B
Z
zhanglinjuan 已提交
260
    s1_valid_dup.foreach(_ := true.B)
261
    s1_valid_dup_for_status.foreach(_ := true.B)
262 263
  }.elsewhen (s1_fire) {
    s1_valid := false.B
Z
zhanglinjuan 已提交
264
    s1_valid_dup.foreach(_ := false.B)
265
    s1_valid_dup_for_status.foreach(_ := false.B)
266
  }
Z
zhanglinjuan 已提交
267 268 269
  s1_ready := !s1_valid_dup(0) || s1_can_go
  s1_s0_set_conflict := s1_valid_dup(1) && s0_idx === s1_idx
  s1_s0_set_conflict_store := s1_valid_dup(2) && store_idx === s1_idx
270

271
  val meta_resp = Wire(Vec(nWays, (new Meta).asUInt()))
Z
zhanglinjuan 已提交
272
  val tag_resp = Wire(Vec(nWays, UInt(tagBits.W)))
273 274 275 276 277 278
  val ecc_resp = Wire(Vec(nWays, UInt(eccTagBits.W)))
  meta_resp := Mux(RegNext(s0_fire), VecInit(io.meta_resp.map(_.asUInt)), RegNext(meta_resp))
  tag_resp := Mux(RegNext(s0_fire), VecInit(io.tag_resp.map(r => r(tagBits - 1, 0))), RegNext(tag_resp))
  ecc_resp := Mux(RegNext(s0_fire), VecInit(io.tag_resp.map(r => r(encTagBits - 1, tagBits))), RegNext(ecc_resp))
  val enc_tag_resp = Wire(io.tag_resp.cloneType)
  enc_tag_resp := Mux(RegNext(s0_fire), io.tag_resp, RegNext(enc_tag_resp))
279 280

  def wayMap[T <: Data](f: Int => T) = VecInit((0 until nWays).map(f))
Z
zhanglinjuan 已提交
281 282
  val s1_tag_eq_way = wayMap((w: Int) => tag_resp(w) === get_tag(s1_req.addr)).asUInt
  val s1_tag_match_way = wayMap((w: Int) => s1_tag_eq_way(w) && Meta(meta_resp(w)).coh.isValid()).asUInt
283 284
  val s1_tag_match = s1_tag_match_way.orR

Z
zhanglinjuan 已提交
285 286
  val s1_hit_tag = Mux(s1_tag_match, Mux1H(s1_tag_match_way, wayMap(w => tag_resp(w))), get_tag(s1_req.addr))
  val s1_hit_coh = ClientMetadata(Mux(s1_tag_match, Mux1H(s1_tag_match_way, wayMap(w => meta_resp(w))), 0.U))
287
  val s1_encTag = Mux1H(s1_tag_match_way, wayMap((w: Int) => enc_tag_resp(w)))
288
  val s1_flag_error = Mux(s1_tag_match, Mux1H(s1_tag_match_way, wayMap(w => io.error_flag_resp(w))), false.B)
289
  val s1_l2_error = s1_req.error
290 291

  // replacement policy
292
  val s1_repl_way_en = WireInit(0.U(nWays.W))
Z
zhanglinjuan 已提交
293 294 295
  s1_repl_way_en := Mux(RegNext(s0_fire), UIntToOH(io.replace_way.way), RegNext(s1_repl_way_en))
  val s1_repl_tag = Mux1H(s1_repl_way_en, wayMap(w => tag_resp(w)))
  val s1_repl_coh = Mux1H(s1_repl_way_en, wayMap(w => meta_resp(w))).asTypeOf(new ClientMetadata)
296 297
  val s1_miss_tag = Mux1H(s1_req.miss_way_en, wayMap(w => tag_resp(w)))
  val s1_miss_coh = Mux1H(s1_req.miss_way_en, wayMap(w => meta_resp(w))).asTypeOf(new ClientMetadata)
298

299 300 301
  val s1_repl_way_raw = WireInit(0.U(log2Up(nWays).W))
  s1_repl_way_raw := Mux(RegNext(s0_fire), io.replace_way.way, RegNext(s1_repl_way_raw))

Z
zhanglinjuan 已提交
302
  val s1_need_replacement = (s1_req.miss || s1_req.isStore && !s1_req.probe) && !s1_tag_match
303 304 305 306 307 308 309 310 311 312 313 314 315
  val s1_way_en = Mux(
    s1_req.replace,
    s1_req.replace_way_en,
    Mux(
      s1_req.miss,
      s1_req.miss_way_en,
      Mux(
        s1_need_replacement,
        s1_repl_way_en,
        s1_tag_match_way
      )
    )
  )
316
  assert(!RegNext(s1_fire && PopCount(s1_way_en) > 1.U))
317 318 319 320 321 322 323 324 325
  val s1_tag = Mux(
    s1_req.replace,
    get_tag(s1_req.addr),
    Mux(
      s1_req.miss,
      s1_miss_tag,
      Mux(s1_need_replacement, s1_repl_tag, s1_hit_tag)
    )
  )
326 327 328
  val s1_coh = Mux(
    s1_req.replace,
    Mux1H(s1_req.replace_way_en, meta_resp.map(ClientMetadata(_))),
329 330 331 332 333
    Mux(
      s1_req.miss,
      s1_miss_coh,
      Mux(s1_need_replacement, s1_repl_coh, s1_hit_coh)
    )
334
  )
335

W
William Wang 已提交
336 337
  val s1_has_permission = s1_hit_coh.onAccess(s1_req.cmd)._1
  val s1_hit = s1_tag_match && s1_has_permission
338
  val s1_pregen_can_go_to_mq = !s1_req.replace && !s1_req.probe && !s1_req.miss && (s1_req.isStore || s1_req.isAMO) && !s1_hit
W
William Wang 已提交
339

Z
zhanglinjuan 已提交
340 341 342
  // s2: select data, return resp if this is a store miss
  val s2_valid = RegInit(false.B)
  val s2_req = RegEnable(s1_req, s1_fire)
343
  val s2_tag_match = RegEnable(s1_tag_match, s1_fire)
344
  val s2_tag_match_way = RegEnable(s1_tag_match_way, s1_fire)
345
  val s2_hit_coh = RegEnable(s1_hit_coh, s1_fire)
Z
zhanglinjuan 已提交
346
  val (s2_has_permission, _, s2_new_hit_coh) = s2_hit_coh.onAccess(s2_req.cmd)
347

Z
zhanglinjuan 已提交
348 349
  val s2_repl_tag = RegEnable(s1_repl_tag, s1_fire)
  val s2_repl_coh = RegEnable(s1_repl_coh, s1_fire)
350
  val s2_repl_way_en = RegEnable(s1_repl_way_en, s1_fire)
351
  val s2_need_replacement = RegEnable(s1_need_replacement, s1_fire)
352
  val s2_need_data = RegEnable(s1_need_data, s1_fire)
353 354
  val s2_need_tag = RegEnable(s1_need_tag, s1_fire)
  val s2_encTag = RegEnable(s1_encTag, s1_fire)
Z
zhanglinjuan 已提交
355
  val s2_idx = get_idx(s2_req.vaddr)
Z
zhanglinjuan 已提交
356 357 358

  // duplicate regs to reduce fanout
  val s2_valid_dup = RegInit(VecInit(Seq.fill(8)(false.B)))
359
  val s2_valid_dup_for_status = RegInit(VecInit(Seq.fill(nDupStatus)(false.B)))
Z
zhanglinjuan 已提交
360 361 362 363 364 365 366 367 368
  val s2_req_vaddr_dup_for_miss_req = RegEnable(s1_req.vaddr, s1_fire)
  val s2_idx_dup_for_status = RegEnable(get_idx(s1_req.vaddr), s1_fire)
  val s2_idx_dup_for_replace_access = RegEnable(get_idx(s1_req.vaddr), s1_fire)

  val s2_req_replace_dup_1,
      s2_req_replace_dup_2 = RegEnable(s1_req.replace, s1_fire)
  
  val s2_can_go_to_mq_dup = (0 until 3).map(_ => RegEnable(s1_pregen_can_go_to_mq, s1_fire))

369
  val s2_way_en = RegEnable(s1_way_en, s1_fire)
Z
zhanglinjuan 已提交
370 371 372
  val s2_tag = RegEnable(s1_tag, s1_fire)
  val s2_coh = RegEnable(s1_coh, s1_fire)
  val s2_banked_store_wmask = RegEnable(s1_banked_store_wmask, s1_fire)
373
  val s2_flag_error = RegEnable(s1_flag_error, s1_fire)
374
  val s2_tag_error = dcacheParameters.tagCode.decode(s2_encTag).error && s2_need_tag
375
  val s2_l2_error = s2_req.error
376 377 378
  val s2_error = s2_flag_error || s2_tag_error || s2_l2_error // data_error not included

  val s2_may_report_data_error = s2_need_data && s2_coh.state =/= ClientStates.Nothing
379 380

  val s2_hit = s2_tag_match && s2_has_permission
Z
zhanglinjuan 已提交
381 382 383
  val s2_amo_hit = s2_hit && !s2_req.probe && !s2_req.miss && s2_req.isAMO
  val s2_store_hit = s2_hit && !s2_req.probe && !s2_req.miss && s2_req.isStore

Z
zhanglinjuan 已提交
384 385
  s2_s0_set_conlict := s2_valid_dup(0) && s0_idx === s2_idx
  s2_s0_set_conlict_store := s2_valid_dup(1) && store_idx === s2_idx
Z
zhanglinjuan 已提交
386 387

  // For a store req, it either hits and goes to s3, or miss and enter miss queue immediately
Z
zhanglinjuan 已提交
388
  val s2_can_go_to_s3 = (s2_req_replace_dup_1 || s2_req.probe || s2_req.miss || (s2_req.isStore || s2_req.isAMO) && s2_hit) && s3_ready
W
William Wang 已提交
389
  val s2_can_go_to_mq = RegEnable(s1_pregen_can_go_to_mq, s1_fire)
Z
zhanglinjuan 已提交
390 391 392
  assert(RegNext(!(s2_valid && s2_can_go_to_s3 && s2_can_go_to_mq)))
  val s2_can_go = s2_can_go_to_s3 || s2_can_go_to_mq
  val s2_fire = s2_valid && s2_can_go
Z
zhanglinjuan 已提交
393
  val s2_fire_to_s3 = s2_valid_dup(2) && s2_can_go_to_s3
Z
zhanglinjuan 已提交
394 395
  when (s1_fire) {
    s2_valid := true.B
Z
zhanglinjuan 已提交
396
    s2_valid_dup.foreach(_ := true.B)
397
    s2_valid_dup_for_status.foreach(_ := true.B)
Z
zhanglinjuan 已提交
398 399
  }.elsewhen (s2_fire) {
    s2_valid := false.B
Z
zhanglinjuan 已提交
400
    s2_valid_dup.foreach(_ := false.B)
401
    s2_valid_dup_for_status.foreach(_ := false.B)
402
  }
Z
zhanglinjuan 已提交
403
  s2_ready := !s2_valid_dup(3) || s2_can_go
W
William Wang 已提交
404
  val replay = !io.miss_req.ready
405

Z
zhanglinjuan 已提交
406 407
  val data_resp = Wire(io.data_resp.cloneType)
  data_resp := Mux(RegNext(s1_fire), io.data_resp, RegNext(data_resp))
408
  val s2_store_data_merged = Wire(Vec(DCacheBanks, UInt(DCacheSRAMRowBits.W)))
409 410 411 412 413

  def mergePutData(old_data: UInt, new_data: UInt, wmask: UInt): UInt = {
    val full_wmask = FillInterleaved(8, wmask)
    ((~full_wmask & old_data) | (full_wmask & new_data))
  }
Y
Yinan Xu 已提交
414

415
  val s2_data = WireInit(VecInit((0 until DCacheBanks).map(i => {
Z
zhanglinjuan 已提交
416
    data_resp(i).raw_data
417 418 419 420 421 422 423 424 425
  })))

  for (i <- 0 until DCacheBanks) {
    val old_data = s2_data(i)
    val new_data = get_data_of_bank(i, s2_req.store_data)
    // for amo hit, we should use read out SRAM data
    // do not merge with store data
    val wmask = Mux(s2_amo_hit, 0.U(wordBytes.W), get_mask_of_bank(i, s2_req.store_mask))
    s2_store_data_merged(i) := mergePutData(old_data, new_data, wmask)
426 427
  }

428
  val s2_data_word = s2_store_data_merged(s2_req.word_idx)
429

Z
zhanglinjuan 已提交
430 431 432
  // s3: write data, meta and tag
  val s3_valid = RegInit(false.B)
  val s3_req = RegEnable(s2_req, s2_fire_to_s3)
Z
zhanglinjuan 已提交
433
  // val s3_idx = get_idx(s3_req.vaddr)
Z
zhanglinjuan 已提交
434 435 436 437 438 439 440 441 442 443 444 445 446
  val s3_tag = RegEnable(s2_tag, s2_fire_to_s3)
  val s3_tag_match = RegEnable(s2_tag_match, s2_fire_to_s3)
  val s3_coh = RegEnable(s2_coh, s2_fire_to_s3)
  val s3_hit = RegEnable(s2_hit, s2_fire_to_s3)
  val s3_amo_hit = RegEnable(s2_amo_hit, s2_fire_to_s3)
  val s3_store_hit = RegEnable(s2_store_hit, s2_fire_to_s3)
  val s3_hit_coh = RegEnable(s2_hit_coh, s2_fire_to_s3)
  val s3_new_hit_coh = RegEnable(s2_new_hit_coh, s2_fire_to_s3)
  val s3_way_en = RegEnable(s2_way_en, s2_fire_to_s3)
  val s3_banked_store_wmask = RegEnable(s2_banked_store_wmask, s2_fire_to_s3)
  val s3_store_data_merged = RegEnable(s2_store_data_merged, s2_fire_to_s3)
  val s3_data_word = RegEnable(s2_data_word, s2_fire_to_s3)
  val s3_data = RegEnable(s2_data, s2_fire_to_s3)
447
  val s3_l2_error = s3_req.error
448 449 450 451 452 453 454 455 456
  // data_error will be reported by data array 1 cycle after data read resp
  val s3_data_error = Wire(Bool())
  s3_data_error := Mux(RegNext(RegNext(s1_fire)), // ecc check result is generated 2 cycle after read req
    io.readline_error_delayed && RegNext(s2_may_report_data_error), 
    RegNext(s3_data_error) // do not update s3_data_error if !s1_fire
  )
  // error signal for amo inst
  // s3_error = s3_flag_error || s3_tag_error || s3_l2_error || s3_data_error
  val s3_error = RegEnable(s2_error, s2_fire_to_s3) || s3_data_error
Z
zhanglinjuan 已提交
457
  val (_, _, probe_new_coh) = s3_coh.onProbe(s3_req.probe_param)
Z
zhanglinjuan 已提交
458
  val s3_need_replacement = RegEnable(s2_need_replacement, s2_fire_to_s3)
459

Z
zhanglinjuan 已提交
460 461 462

  // duplicate regs to reduce fanout
  val s3_valid_dup = RegInit(VecInit(Seq.fill(14)(false.B)))
463
  val s3_valid_dup_for_status = RegInit(VecInit(Seq.fill(nDupStatus)(false.B)))
Z
zhanglinjuan 已提交
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
  val s3_way_en_dup = (0 until 4).map(_ => RegEnable(s2_way_en, s2_fire_to_s3))
  val s3_coh_dup = (0 until 6).map(_ => RegEnable(s2_coh, s2_fire_to_s3))
  val s3_tag_match_dup = RegEnable(s2_tag_match, s2_fire_to_s3)

  val s3_req_vaddr_dup_for_wb,
      s3_req_vaddr_dup_for_data_write = RegEnable(s2_req.vaddr, s2_fire_to_s3)
  
  val s3_idx_dup = (0 until 6).map(_ => RegEnable(get_idx(s2_req.vaddr), s2_fire_to_s3))

  val s3_req_replace_dup = (0 until 8).map(_ => RegEnable(s2_req.replace, s2_fire_to_s3))    
  val s3_req_cmd_dup = (0 until 6).map(_ => RegEnable(s2_req.cmd, s2_fire_to_s3))
  val s3_req_source_dup_1, s3_req_source_dup_2 = RegEnable(s2_req.source, s2_fire_to_s3)
  val s3_req_addr_dup = (0 until 5).map(_ => RegEnable(s2_req.addr, s2_fire_to_s3))
  val s3_req_probe_dup = (0 until 10).map(_ => RegEnable(s2_req.probe, s2_fire_to_s3))
  val s3_req_miss_dup = (0 until 10).map(_ => RegEnable(s2_req.miss, s2_fire_to_s3))
  val s3_req_word_idx_dup = (0 until DCacheBanks).map(_ => RegEnable(s2_req.word_idx, s2_fire_to_s3))

  val s3_need_replacement_dup = RegEnable(s2_need_replacement, s2_fire_to_s3)

  val s3_s_amoalu_dup = RegInit(VecInit(Seq.fill(3)(false.B)))

  val s3_hit_coh_dup = RegEnable(s2_hit_coh, s2_fire_to_s3)
  val s3_new_hit_coh_dup = (0 until 2).map(_ => RegEnable(s2_new_hit_coh, s2_fire_to_s3))
  val s3_amo_hit_dup = RegEnable(s2_amo_hit, s2_fire_to_s3)
  val s3_store_hit_dup = (0 until 2).map(_ => RegEnable(s2_store_hit, s2_fire_to_s3))

  val lrsc_count_dup = RegInit(VecInit(Seq.fill(3)(0.U(log2Ceil(LRSCCycles).W))))
  val lrsc_valid_dup = lrsc_count_dup.map { case cnt => cnt > LRSCBackOff.U }
  val lrsc_addr_dup = Reg(UInt())

  val s3_req_probe_param_dup = RegEnable(s2_req.probe_param, s2_fire_to_s3)
  val (_, probe_shrink_param, _) = s3_coh.onProbe(s3_req_probe_param_dup)


Z
zhanglinjuan 已提交
498
  val miss_update_meta = s3_req.miss
Z
zhanglinjuan 已提交
499 500 501 502 503
  val probe_update_meta = s3_req_probe_dup(0) && s3_tag_match_dup && s3_coh_dup(0) =/= probe_new_coh
  val store_update_meta = s3_req.isStore && !s3_req_probe_dup(1) && s3_hit_coh =/= s3_new_hit_coh_dup(0)
  val amo_update_meta = s3_req.isAMO && !s3_req_probe_dup(2) && s3_hit_coh_dup =/= s3_new_hit_coh_dup(1)
  val amo_wait_amoalu = s3_req.isAMO && s3_req_cmd_dup(0) =/= M_XLR && s3_req_cmd_dup(1) =/= M_XSC
  val update_meta = (miss_update_meta || probe_update_meta || store_update_meta || amo_update_meta) && !s3_req_replace_dup(0)
504

505 506 507 508 509 510 511 512 513 514 515 516 517
  def missCohGen(cmd: UInt, param: UInt, dirty: Bool) = {
    val c = categorize(cmd)
    MuxLookup(Cat(c, param, dirty), Nothing, Seq(
      //(effect param) -> (next)
      Cat(rd, toB, false.B)  -> Branch,
      Cat(rd, toB, true.B)   -> Branch,
      Cat(rd, toT, false.B)  -> Trunk,
      Cat(rd, toT, true.B)   -> Dirty,
      Cat(wi, toT, false.B)  -> Trunk,
      Cat(wi, toT, true.B)   -> Dirty,
      Cat(wr, toT, false.B)  -> Dirty,
      Cat(wr, toT, true.B)   -> Dirty))
  }
Z
zhanglinjuan 已提交
518
  val miss_new_coh = ClientMetadata(missCohGen(s3_req_cmd_dup(2), s3_req.miss_param, s3_req.miss_dirty))
519 520 521 522 523

  // LR, SC and AMO
  val debug_sc_fail_addr = RegInit(0.U)
  val debug_sc_fail_cnt  = RegInit(0.U(8.W))

524
  val lrsc_count = RegInit(0.U(log2Ceil(LRSCCycles).W))
Z
zhanglinjuan 已提交
525
  // val lrsc_valid = lrsc_count > LRSCBackOff.U
526
  val lrsc_addr  = Reg(UInt())
Z
zhanglinjuan 已提交
527 528 529
  val s3_lr = !s3_req_probe_dup(3) && s3_req.isAMO && s3_req_cmd_dup(3) === M_XLR
  val s3_sc = !s3_req_probe_dup(4) && s3_req.isAMO && s3_req_cmd_dup(4) === M_XSC
  val s3_lrsc_addr_match = lrsc_valid_dup(0) && lrsc_addr === get_block_addr(s3_req.addr)
530 531 532
  val s3_sc_fail = s3_sc && !s3_lrsc_addr_match
  val s3_sc_resp = Mux(s3_sc_fail, 1.U, 0.U)

Z
zhanglinjuan 已提交
533 534
  val s3_can_do_amo = (s3_req_miss_dup(0) && !s3_req_probe_dup(5) && s3_req.isAMO) || s3_amo_hit
  val s3_can_do_amo_write = s3_can_do_amo && isWrite(s3_req_cmd_dup(5)) && !s3_sc_fail
Z
zhanglinjuan 已提交
535

Z
zhanglinjuan 已提交
536
  when (s3_valid_dup(0) && (s3_lr || s3_sc)) {
537
    when (s3_can_do_amo && s3_lr) {
538
      lrsc_count := (LRSCCycles - 1).U
Z
zhanglinjuan 已提交
539 540 541
      lrsc_count_dup.foreach(_ := (LRSCCycles - 1).U)
      lrsc_addr := get_block_addr(s3_req_addr_dup(0))
      lrsc_addr_dup := get_block_addr(s3_req_addr_dup(0))
542 543
    } .otherwise {
      lrsc_count := 0.U
Z
zhanglinjuan 已提交
544
      lrsc_count_dup.foreach(_ := 0.U)
545
    }
546 547 548 549
  } .elsewhen (io.invalid_resv_set) {
    // when we release this block,
    // we invalidate this reservation set
    lrsc_count := 0.U
550 551
  } .elsewhen (lrsc_count > 0.U) {
    lrsc_count := lrsc_count - 1.U
Z
zhanglinjuan 已提交
552 553 554
    lrsc_count_dup.foreach({case cnt =>
      cnt := cnt - 1.U
    })
555 556
  }

Z
zhanglinjuan 已提交
557 558
  io.lrsc_locked_block.valid := lrsc_valid_dup(1)
  io.lrsc_locked_block.bits  := lrsc_addr_dup
559
  io.block_lr := RegNext(lrsc_count > 0.U)
560

W
William Wang 已提交
561 562 563
  // When we update update_resv_set, block all probe req in the next cycle
  // It should give Probe reservation set addr compare an independent cycle,
  // which will lead to better timing
Z
zhanglinjuan 已提交
564
  io.update_resv_set := s3_valid_dup(1) && s3_lr && s3_can_do_amo
W
William Wang 已提交
565

Z
zhanglinjuan 已提交
566 567 568 569 570 571 572 573 574
  // when we release this block,
  // we invalidate this reservation set
  when (io.invalid_resv_set) {
    lrsc_count := 0.U
    lrsc_count_dup.foreach(_ := 0.U)
  }

  when (s3_valid_dup(2)) {
    when (s3_req_addr_dup(1) === debug_sc_fail_addr) {
575 576 577 578 579 580 581
      when (s3_sc_fail) {
        debug_sc_fail_cnt := debug_sc_fail_cnt + 1.U
      } .elsewhen (s3_sc) {
        debug_sc_fail_cnt := 0.U
      }
    } .otherwise {
      when (s3_sc_fail) {
Z
zhanglinjuan 已提交
582
        debug_sc_fail_addr := s3_req_addr_dup(2)
583
        debug_sc_fail_cnt  := 1.U
584
        XSWarn(s3_sc_fail === 100.U, p"L1DCache failed too many SCs in a row 0x${Hexadecimal(debug_sc_fail_addr)}, check if sth went wrong\n")
585 586 587
      }
    }
  }
588
  // assert(debug_sc_fail_cnt < 100.U, "L1DCache failed too many SCs in a row")
Z
zhanglinjuan 已提交
589

590
  val banked_amo_wmask = UIntToOH(s3_req.word_idx)
Z
zhanglinjuan 已提交
591
  val update_data = s3_req_miss_dup(2) || s3_store_hit_dup(0) || s3_can_do_amo_write
592 593 594

  // generate write data
  // AMO hits
W
William Wang 已提交
595
  val s3_s_amoalu = RegInit(false.B)
Z
zhanglinjuan 已提交
596
  val do_amoalu = amo_wait_amoalu && s3_valid_dup(3) && !s3_s_amoalu
597 598 599 600 601 602 603
  val amoalu   = Module(new AMOALU(wordBits))
  amoalu.io.mask := s3_req.amo_mask
  amoalu.io.cmd  := s3_req.cmd
  amoalu.io.lhs  := s3_data_word
  amoalu.io.rhs  := s3_req.amo_data

  // merge amo write data
604
//  val amo_bitmask = FillInterleaved(8, s3_req.amo_mask)
605
  val s3_amo_data_merged = Wire(Vec(DCacheBanks, UInt(DCacheSRAMRowBits.W)))
W
William Wang 已提交
606
  val s3_sc_data_merged = Wire(Vec(DCacheBanks, UInt(DCacheSRAMRowBits.W)))
607 608 609
  for (i <- 0 until DCacheBanks) {
    val old_data = s3_store_data_merged(i)
    val new_data = amoalu.io.out
W
William Wang 已提交
610
    val wmask = Mux(
Z
zhanglinjuan 已提交
611
      s3_req_word_idx_dup(i) === i.U,
W
William Wang 已提交
612 613 614
      ~0.U(wordBytes.W),
      0.U(wordBytes.W)
    )
615
    s3_amo_data_merged(i) := mergePutData(old_data, new_data, wmask)
616
    s3_sc_data_merged(i) := mergePutData(old_data, s3_req.amo_data,
Z
zhanglinjuan 已提交
617
      Mux(s3_req_word_idx_dup(i) === i.U && !s3_sc_fail, s3_req.amo_mask, 0.U(wordBytes.W))
618
    )
W
William Wang 已提交
619 620 621 622
  }
  val s3_amo_data_merged_reg = RegEnable(s3_amo_data_merged, do_amoalu)
  when(do_amoalu){
    s3_s_amoalu := true.B
Z
zhanglinjuan 已提交
623
    s3_s_amoalu_dup.foreach(_ := true.B)
624 625
  }

Z
zhanglinjuan 已提交
626 627
  val miss_wb = s3_req_miss_dup(3) && s3_need_replacement && s3_coh_dup(1).state =/= ClientStates.Nothing
  val miss_wb_dup = s3_req_miss_dup(3) && s3_need_replacement_dup && s3_coh_dup(1).state =/= ClientStates.Nothing
Z
zhanglinjuan 已提交
628
  val probe_wb = s3_req.probe
629
  val replace_wb = s3_req.replace
Z
zhanglinjuan 已提交
630
  val need_wb = miss_wb_dup || probe_wb || replace_wb
631

Z
zhanglinjuan 已提交
632
  val (_, miss_shrink_param, _) = s3_coh_dup(2).onCacheControl(M_FLUSH)
633
  val writeback_param = Mux(probe_wb, probe_shrink_param, miss_shrink_param)
634
  val writeback_data = if (dcacheParameters.alwaysReleaseData) {
Z
zhanglinjuan 已提交
635 636
    s3_tag_match && s3_req_probe_dup(6) && s3_req.probe_need_data ||
      s3_coh_dup(3) === ClientStates.Dirty || (miss_wb || replace_wb) && s3_coh_dup(3).state =/= ClientStates.Nothing
637
  } else {
Z
zhanglinjuan 已提交
638
    s3_tag_match && s3_req_probe_dup(6) && s3_req.probe_need_data || s3_coh_dup(3) === ClientStates.Dirty
639
  }
640

Z
zhanglinjuan 已提交
641 642 643 644
  val s3_probe_can_go = s3_req_probe_dup(7) && io.wb.ready && (io.meta_write.ready || !probe_update_meta)
  val s3_store_can_go = s3_req_source_dup_1 === STORE_SOURCE.U && !s3_req_probe_dup(8) && (io.meta_write.ready || !store_update_meta) && (io.data_write.ready || !update_data)
  val s3_amo_can_go = s3_amo_hit_dup && (io.meta_write.ready || !amo_update_meta) && (io.data_write.ready || !update_data) && (s3_s_amoalu_dup(0) || !amo_wait_amoalu)
  val s3_miss_can_go = s3_req_miss_dup(4) &&
Z
zhanglinjuan 已提交
645 646
    (io.meta_write.ready || !amo_update_meta) &&
    (io.data_write.ready || !update_data) &&
Z
zhanglinjuan 已提交
647
    (s3_s_amoalu_dup(1) || !amo_wait_amoalu) &&
Z
zhanglinjuan 已提交
648 649
    io.tag_write.ready &&
    io.wb.ready
Z
zhanglinjuan 已提交
650 651
  val s3_replace_nothing = s3_req_replace_dup(1) && s3_coh_dup(4).state === ClientStates.Nothing
  val s3_replace_can_go = s3_req_replace_dup(2) && (s3_replace_nothing || io.wb.ready)
652
  val s3_can_go = s3_probe_can_go || s3_store_can_go || s3_amo_can_go || s3_miss_can_go || s3_replace_can_go
653
  val s3_update_data_cango = s3_store_can_go || s3_amo_can_go || s3_miss_can_go // used to speed up data_write gen
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744

  // ---------------- duplicate regs for meta_write.valid to solve fanout ----------------
  val s3_req_miss_dup_for_meta_w_valid = RegEnable(s2_req.miss, s2_fire_to_s3)
  val s3_req_probe_dup_for_meta_w_valid = RegEnable(s2_req.probe, s2_fire_to_s3)
  val s3_tag_match_dup_for_meta_w_valid = RegEnable(s2_tag_match, s2_fire_to_s3)
  val s3_coh_dup_for_meta_w_valid = RegEnable(s2_coh, s2_fire_to_s3)
  val s3_req_probe_param_dup_for_meta_w_valid = RegEnable(s2_req.probe_param, s2_fire_to_s3)
  val (_, _, probe_new_coh_dup_for_meta_w_valid) = s3_coh_dup_for_meta_w_valid.onProbe(s3_req_probe_param_dup_for_meta_w_valid)
  val s3_req_source_dup_for_meta_w_valid = RegEnable(s2_req.source, s2_fire_to_s3)
  val s3_req_cmd_dup_for_meta_w_valid = RegEnable(s2_req.cmd, s2_fire_to_s3)
  val s3_req_replace_dup_for_meta_w_valid = RegEnable(s2_req.replace, s2_fire_to_s3)
  val s3_hit_coh_dup_for_meta_w_valid = RegEnable(s2_hit_coh, s2_fire_to_s3)
  val s3_new_hit_coh_dup_for_meta_w_valid = RegEnable(s2_new_hit_coh, s2_fire_to_s3)
  
  val miss_update_meta_dup_for_meta_w_valid = s3_req_miss_dup_for_meta_w_valid
  val probe_update_meta_dup_for_meta_w_valid = s3_req_probe_dup_for_meta_w_valid && s3_tag_match_dup_for_meta_w_valid && s3_coh_dup_for_meta_w_valid =/= probe_new_coh_dup_for_meta_w_valid
  val store_update_meta_dup_for_meta_w_valid = s3_req_source_dup_for_meta_w_valid === STORE_SOURCE.U &&
    !s3_req_probe_dup_for_meta_w_valid &&
    s3_hit_coh_dup_for_meta_w_valid =/= s3_new_hit_coh_dup_for_meta_w_valid
  val amo_update_meta_dup_for_meta_w_valid = s3_req_source_dup_for_meta_w_valid === AMO_SOURCE.U &&
    !s3_req_probe_dup_for_meta_w_valid &&
    s3_hit_coh_dup_for_meta_w_valid =/= s3_new_hit_coh_dup_for_meta_w_valid
  val update_meta_dup_for_meta_w_valid = (
    miss_update_meta_dup_for_meta_w_valid ||
    probe_update_meta_dup_for_meta_w_valid ||
    store_update_meta_dup_for_meta_w_valid ||
    amo_update_meta_dup_for_meta_w_valid
  ) && !s3_req_replace_dup_for_meta_w_valid

  val s3_valid_dup_for_meta_w_valid = RegInit(false.B)
  val s3_amo_hit_dup_for_meta_w_valid = RegEnable(s2_amo_hit, s2_fire_to_s3)
  val s3_s_amoalu_dup_for_meta_w_valid = RegInit(false.B)
  val amo_wait_amoalu_dup_for_meta_w_valid = s3_req_source_dup_for_meta_w_valid === AMO_SOURCE.U &&
    s3_req_cmd_dup_for_meta_w_valid =/= M_XLR &&
    s3_req_cmd_dup_for_meta_w_valid =/= M_XSC
  val do_amoalu_dup_for_meta_w_valid = amo_wait_amoalu_dup_for_meta_w_valid && s3_valid_dup_for_meta_w_valid && !s3_s_amoalu_dup_for_meta_w_valid

  val s3_store_hit_dup_for_meta_w_valid = RegEnable(s2_store_hit, s2_fire_to_s3)
  val s3_req_addr_dup_for_meta_w_valid = RegEnable(s2_req.addr, s2_fire_to_s3)
  val s3_can_do_amo_dup_for_meta_w_valid = (s3_req_miss_dup_for_meta_w_valid && !s3_req_probe_dup_for_meta_w_valid && s3_req_source_dup_for_meta_w_valid === AMO_SOURCE.U) ||
    s3_amo_hit_dup_for_meta_w_valid

  val s3_lr_dup_for_meta_w_valid = !s3_req_probe_dup_for_meta_w_valid && s3_req_source_dup_for_meta_w_valid === AMO_SOURCE.U && s3_req_cmd_dup_for_meta_w_valid === M_XLR
  val s3_sc_dup_for_meta_w_valid = !s3_req_probe_dup_for_meta_w_valid && s3_req_source_dup_for_meta_w_valid === AMO_SOURCE.U && s3_req_cmd_dup_for_meta_w_valid === M_XSC
  val lrsc_addr_dup_for_meta_w_valid = Reg(UInt())
  val lrsc_count_dup_for_meta_w_valid = RegInit(0.U(log2Ceil(LRSCCycles).W))

  when (s3_valid_dup_for_meta_w_valid && (s3_lr_dup_for_meta_w_valid || s3_sc_dup_for_meta_w_valid)) {
    when (s3_can_do_amo_dup_for_meta_w_valid && s3_lr_dup_for_meta_w_valid) {
      lrsc_count_dup_for_meta_w_valid := (LRSCCycles - 1).U
      lrsc_addr_dup_for_meta_w_valid := get_block_addr(s3_req_addr_dup_for_meta_w_valid)
    }.otherwise {
      lrsc_count_dup_for_meta_w_valid := 0.U
    }
  }.elsewhen (lrsc_count_dup_for_meta_w_valid > 0.U) {
    lrsc_count_dup_for_meta_w_valid := lrsc_count_dup_for_meta_w_valid - 1.U
  }

  val lrsc_valid_dup_for_meta_w_valid = lrsc_count_dup_for_meta_w_valid > LRSCBackOff.U
  val s3_lrsc_addr_match_dup_for_meta_w_valid = lrsc_valid_dup_for_meta_w_valid && lrsc_addr_dup_for_meta_w_valid === get_block_addr(s3_req_addr_dup_for_meta_w_valid)
  val s3_sc_fail_dup_for_meta_w_valid = s3_sc_dup_for_meta_w_valid && !s3_lrsc_addr_match_dup_for_meta_w_valid
  val s3_can_do_amo_write_dup_for_meta_w_valid = s3_can_do_amo_dup_for_meta_w_valid && isWrite(s3_req_cmd_dup_for_meta_w_valid) && !s3_sc_fail_dup_for_meta_w_valid
  val update_data_dup_for_meta_w_valid = s3_req_miss_dup_for_meta_w_valid || s3_store_hit_dup_for_meta_w_valid || s3_can_do_amo_write_dup_for_meta_w_valid

  val s3_probe_can_go_dup_for_meta_w_valid = s3_req_probe_dup_for_meta_w_valid &&
    io.wb_ready_dup(metaWritePort) &&
    (io.meta_write.ready || !probe_update_meta_dup_for_meta_w_valid)
  val s3_store_can_go_dup_for_meta_w_valid = s3_req_source_dup_for_meta_w_valid === STORE_SOURCE.U && !s3_req_probe_dup_for_meta_w_valid &&
    (io.meta_write.ready || !store_update_meta_dup_for_meta_w_valid) &&
    (io.data_write_ready_dup(metaWritePort) || !update_data_dup_for_meta_w_valid)
  val s3_amo_can_go_dup_for_meta_w_valid = s3_amo_hit_dup_for_meta_w_valid &&
    (io.meta_write.ready || !amo_update_meta_dup_for_meta_w_valid) &&
    (io.data_write_ready_dup(metaWritePort) || !update_data_dup_for_meta_w_valid) &&
    (s3_s_amoalu_dup_for_meta_w_valid || !amo_wait_amoalu_dup_for_meta_w_valid)
  val s3_miss_can_go_dup_for_meta_w_valid = s3_req_miss_dup_for_meta_w_valid &&
    (io.meta_write.ready || !amo_update_meta_dup_for_meta_w_valid) &&
    (io.data_write_ready_dup(metaWritePort) || !update_data_dup_for_meta_w_valid) &&
    (s3_s_amoalu_dup_for_meta_w_valid || !amo_wait_amoalu_dup_for_meta_w_valid) &&
    io.tag_write_ready_dup(metaWritePort) &&
    io.wb_ready_dup(metaWritePort)
  val s3_replace_can_go_dup_for_meta_w_valid = s3_req_replace_dup_for_meta_w_valid &&
    (s3_coh_dup_for_meta_w_valid.state === ClientStates.Nothing || io.wb_ready_dup(metaWritePort))
  val s3_can_go_dup_for_meta_w_valid = s3_probe_can_go_dup_for_meta_w_valid ||
    s3_store_can_go_dup_for_meta_w_valid ||
    s3_amo_can_go_dup_for_meta_w_valid ||
    s3_miss_can_go_dup_for_meta_w_valid ||
    s3_replace_can_go_dup_for_meta_w_valid

  val s3_fire_dup_for_meta_w_valid = s3_valid_dup_for_meta_w_valid && s3_can_go_dup_for_meta_w_valid
  when (do_amoalu_dup_for_meta_w_valid) { s3_s_amoalu_dup_for_meta_w_valid := true.B }
  when (s3_fire_dup_for_meta_w_valid) { s3_s_amoalu_dup_for_meta_w_valid := false.B }
745 746 747 748 749 750 751 752 753 754 755 756 757 758

  val new_coh = Mux(
    miss_update_meta_dup_for_meta_w_valid,
    miss_new_coh,
    Mux(
      probe_update_meta,
      probe_new_coh_dup_for_meta_w_valid,
      Mux(
        store_update_meta_dup_for_meta_w_valid || amo_update_meta_dup_for_meta_w_valid,
        s3_new_hit_coh_dup_for_meta_w_valid,
        ClientMetadata.onReset
      )
    )
  )
759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
  // -------------------------------------------------------------------------------------

  // ---------------- duplicate regs for err_write.valid to solve fanout -----------------
  val s3_req_miss_dup_for_err_w_valid = RegEnable(s2_req.miss, s2_fire_to_s3)
  val s3_req_probe_dup_for_err_w_valid = RegEnable(s2_req.probe, s2_fire_to_s3)
  val s3_tag_match_dup_for_err_w_valid = RegEnable(s2_tag_match, s2_fire_to_s3)
  val s3_coh_dup_for_err_w_valid = RegEnable(s2_coh, s2_fire_to_s3)
  val s3_req_probe_param_dup_for_err_w_valid = RegEnable(s2_req.probe_param, s2_fire_to_s3)
  val (_, _, probe_new_coh_dup_for_err_w_valid) = s3_coh_dup_for_err_w_valid.onProbe(s3_req_probe_param_dup_for_err_w_valid)
  val s3_req_source_dup_for_err_w_valid = RegEnable(s2_req.source, s2_fire_to_s3)
  val s3_req_cmd_dup_for_err_w_valid = RegEnable(s2_req.cmd, s2_fire_to_s3)
  val s3_req_replace_dup_for_err_w_valid = RegEnable(s2_req.replace, s2_fire_to_s3)
  val s3_hit_coh_dup_for_err_w_valid = RegEnable(s2_hit_coh, s2_fire_to_s3)
  val s3_new_hit_coh_dup_for_err_w_valid = RegEnable(s2_new_hit_coh, s2_fire_to_s3)
  
  val miss_update_meta_dup_for_err_w_valid = s3_req_miss_dup_for_err_w_valid
  val probe_update_meta_dup_for_err_w_valid = s3_req_probe_dup_for_err_w_valid && s3_tag_match_dup_for_err_w_valid && s3_coh_dup_for_err_w_valid =/= probe_new_coh_dup_for_err_w_valid
  val store_update_meta_dup_for_err_w_valid = s3_req_source_dup_for_err_w_valid === STORE_SOURCE.U &&
    !s3_req_probe_dup_for_err_w_valid &&
    s3_hit_coh_dup_for_err_w_valid =/= s3_new_hit_coh_dup_for_err_w_valid
  val amo_update_meta_dup_for_err_w_valid = s3_req_source_dup_for_err_w_valid === AMO_SOURCE.U &&
    !s3_req_probe_dup_for_err_w_valid &&
    s3_hit_coh_dup_for_err_w_valid =/= s3_new_hit_coh_dup_for_err_w_valid
  val update_meta_dup_for_err_w_valid = (
    miss_update_meta_dup_for_err_w_valid ||
    probe_update_meta_dup_for_err_w_valid ||
    store_update_meta_dup_for_err_w_valid ||
    amo_update_meta_dup_for_err_w_valid
  ) && !s3_req_replace_dup_for_err_w_valid

  val s3_valid_dup_for_err_w_valid = RegInit(false.B)
  val s3_amo_hit_dup_for_err_w_valid = RegEnable(s2_amo_hit, s2_fire_to_s3)
  val s3_s_amoalu_dup_for_err_w_valid = RegInit(false.B)
  val amo_wait_amoalu_dup_for_err_w_valid = s3_req_source_dup_for_err_w_valid === AMO_SOURCE.U &&
    s3_req_cmd_dup_for_err_w_valid =/= M_XLR &&
    s3_req_cmd_dup_for_err_w_valid =/= M_XSC
  val do_amoalu_dup_for_err_w_valid = amo_wait_amoalu_dup_for_err_w_valid && s3_valid_dup_for_err_w_valid && !s3_s_amoalu_dup_for_err_w_valid

  val s3_store_hit_dup_for_err_w_valid = RegEnable(s2_store_hit, s2_fire_to_s3)
  val s3_req_addr_dup_for_err_w_valid = RegEnable(s2_req.addr, s2_fire_to_s3)
  val s3_can_do_amo_dup_for_err_w_valid = (s3_req_miss_dup_for_err_w_valid && !s3_req_probe_dup_for_err_w_valid && s3_req_source_dup_for_err_w_valid === AMO_SOURCE.U) ||
    s3_amo_hit_dup_for_err_w_valid

  val s3_lr_dup_for_err_w_valid = !s3_req_probe_dup_for_err_w_valid && s3_req_source_dup_for_err_w_valid === AMO_SOURCE.U && s3_req_cmd_dup_for_err_w_valid === M_XLR
  val s3_sc_dup_for_err_w_valid = !s3_req_probe_dup_for_err_w_valid && s3_req_source_dup_for_err_w_valid === AMO_SOURCE.U && s3_req_cmd_dup_for_err_w_valid === M_XSC
  val lrsc_addr_dup_for_err_w_valid = Reg(UInt())
  val lrsc_count_dup_for_err_w_valid = RegInit(0.U(log2Ceil(LRSCCycles).W))

  when (s3_valid_dup_for_err_w_valid && (s3_lr_dup_for_err_w_valid || s3_sc_dup_for_err_w_valid)) {
    when (s3_can_do_amo_dup_for_err_w_valid && s3_lr_dup_for_err_w_valid) {
      lrsc_count_dup_for_err_w_valid := (LRSCCycles - 1).U
      lrsc_addr_dup_for_err_w_valid := get_block_addr(s3_req_addr_dup_for_err_w_valid)
    }.otherwise {
      lrsc_count_dup_for_err_w_valid := 0.U
    }
  }.elsewhen (lrsc_count_dup_for_err_w_valid > 0.U) {
    lrsc_count_dup_for_err_w_valid := lrsc_count_dup_for_err_w_valid - 1.U
  }

  val lrsc_valid_dup_for_err_w_valid = lrsc_count_dup_for_err_w_valid > LRSCBackOff.U
  val s3_lrsc_addr_match_dup_for_err_w_valid = lrsc_valid_dup_for_err_w_valid && lrsc_addr_dup_for_err_w_valid === get_block_addr(s3_req_addr_dup_for_err_w_valid)
  val s3_sc_fail_dup_for_err_w_valid = s3_sc_dup_for_err_w_valid && !s3_lrsc_addr_match_dup_for_err_w_valid
  val s3_can_do_amo_write_dup_for_err_w_valid = s3_can_do_amo_dup_for_err_w_valid && isWrite(s3_req_cmd_dup_for_err_w_valid) && !s3_sc_fail_dup_for_err_w_valid
  val update_data_dup_for_err_w_valid = s3_req_miss_dup_for_err_w_valid || s3_store_hit_dup_for_err_w_valid || s3_can_do_amo_write_dup_for_err_w_valid

  val s3_probe_can_go_dup_for_err_w_valid = s3_req_probe_dup_for_err_w_valid &&
    io.wb_ready_dup(errWritePort) &&
    (io.meta_write.ready || !probe_update_meta_dup_for_err_w_valid)
  val s3_store_can_go_dup_for_err_w_valid = s3_req_source_dup_for_err_w_valid === STORE_SOURCE.U && !s3_req_probe_dup_for_err_w_valid &&
    (io.meta_write.ready || !store_update_meta_dup_for_err_w_valid) &&
    (io.data_write_ready_dup(errWritePort) || !update_data_dup_for_err_w_valid)
  val s3_amo_can_go_dup_for_err_w_valid = s3_amo_hit_dup_for_err_w_valid &&
    (io.meta_write.ready || !amo_update_meta_dup_for_err_w_valid) &&
    (io.data_write_ready_dup(errWritePort) || !update_data_dup_for_err_w_valid) &&
    (s3_s_amoalu_dup_for_err_w_valid || !amo_wait_amoalu_dup_for_err_w_valid)
  val s3_miss_can_go_dup_for_err_w_valid = s3_req_miss_dup_for_err_w_valid &&
    (io.meta_write.ready || !amo_update_meta_dup_for_err_w_valid) &&
    (io.data_write_ready_dup(errWritePort) || !update_data_dup_for_err_w_valid) &&
    (s3_s_amoalu_dup_for_err_w_valid || !amo_wait_amoalu_dup_for_err_w_valid) &&
    io.tag_write_ready_dup(errWritePort) &&
    io.wb_ready_dup(errWritePort)
  val s3_replace_can_go_dup_for_err_w_valid = s3_req_replace_dup_for_err_w_valid &&
    (s3_coh_dup_for_err_w_valid.state === ClientStates.Nothing || io.wb_ready_dup(errWritePort))
  val s3_can_go_dup_for_err_w_valid = s3_probe_can_go_dup_for_err_w_valid ||
    s3_store_can_go_dup_for_err_w_valid ||
    s3_amo_can_go_dup_for_err_w_valid ||
    s3_miss_can_go_dup_for_err_w_valid ||
    s3_replace_can_go_dup_for_err_w_valid

  val s3_fire_dup_for_err_w_valid = s3_valid_dup_for_err_w_valid && s3_can_go_dup_for_err_w_valid
  when (do_amoalu_dup_for_err_w_valid) { s3_s_amoalu_dup_for_err_w_valid := true.B }
  when (s3_fire_dup_for_err_w_valid) { s3_s_amoalu_dup_for_err_w_valid := false.B }
  // -------------------------------------------------------------------------------------
  // ---------------- duplicate regs for tag_write.valid to solve fanout -----------------
  val s3_req_miss_dup_for_tag_w_valid = RegEnable(s2_req.miss, s2_fire_to_s3)
  val s3_req_probe_dup_for_tag_w_valid = RegEnable(s2_req.probe, s2_fire_to_s3)
  val s3_tag_match_dup_for_tag_w_valid = RegEnable(s2_tag_match, s2_fire_to_s3)
  val s3_coh_dup_for_tag_w_valid = RegEnable(s2_coh, s2_fire_to_s3)
  val s3_req_probe_param_dup_for_tag_w_valid = RegEnable(s2_req.probe_param, s2_fire_to_s3)
  val (_, _, probe_new_coh_dup_for_tag_w_valid) = s3_coh_dup_for_tag_w_valid.onProbe(s3_req_probe_param_dup_for_tag_w_valid)
  val s3_req_source_dup_for_tag_w_valid = RegEnable(s2_req.source, s2_fire_to_s3)
  val s3_req_cmd_dup_for_tag_w_valid = RegEnable(s2_req.cmd, s2_fire_to_s3)
  val s3_req_replace_dup_for_tag_w_valid = RegEnable(s2_req.replace, s2_fire_to_s3)
  val s3_hit_coh_dup_for_tag_w_valid = RegEnable(s2_hit_coh, s2_fire_to_s3)
  val s3_new_hit_coh_dup_for_tag_w_valid = RegEnable(s2_new_hit_coh, s2_fire_to_s3)
  
  val miss_update_meta_dup_for_tag_w_valid = s3_req_miss_dup_for_tag_w_valid
  val probe_update_meta_dup_for_tag_w_valid = s3_req_probe_dup_for_tag_w_valid && s3_tag_match_dup_for_tag_w_valid && s3_coh_dup_for_tag_w_valid =/= probe_new_coh_dup_for_tag_w_valid
  val store_update_meta_dup_for_tag_w_valid = s3_req_source_dup_for_tag_w_valid === STORE_SOURCE.U &&
    !s3_req_probe_dup_for_tag_w_valid &&
    s3_hit_coh_dup_for_tag_w_valid =/= s3_new_hit_coh_dup_for_tag_w_valid
  val amo_update_meta_dup_for_tag_w_valid = s3_req_source_dup_for_tag_w_valid === AMO_SOURCE.U &&
    !s3_req_probe_dup_for_tag_w_valid &&
    s3_hit_coh_dup_for_tag_w_valid =/= s3_new_hit_coh_dup_for_tag_w_valid
  val update_meta_dup_for_tag_w_valid = (
    miss_update_meta_dup_for_tag_w_valid ||
    probe_update_meta_dup_for_tag_w_valid ||
    store_update_meta_dup_for_tag_w_valid ||
    amo_update_meta_dup_for_tag_w_valid
  ) && !s3_req_replace_dup_for_tag_w_valid

  val s3_valid_dup_for_tag_w_valid = RegInit(false.B)
  val s3_amo_hit_dup_for_tag_w_valid = RegEnable(s2_amo_hit, s2_fire_to_s3)
  val s3_s_amoalu_dup_for_tag_w_valid = RegInit(false.B)
  val amo_wait_amoalu_dup_for_tag_w_valid = s3_req_source_dup_for_tag_w_valid === AMO_SOURCE.U &&
    s3_req_cmd_dup_for_tag_w_valid =/= M_XLR &&
    s3_req_cmd_dup_for_tag_w_valid =/= M_XSC
  val do_amoalu_dup_for_tag_w_valid = amo_wait_amoalu_dup_for_tag_w_valid && s3_valid_dup_for_tag_w_valid && !s3_s_amoalu_dup_for_tag_w_valid

  val s3_store_hit_dup_for_tag_w_valid = RegEnable(s2_store_hit, s2_fire_to_s3)
  val s3_req_addr_dup_for_tag_w_valid = RegEnable(s2_req.addr, s2_fire_to_s3)
  val s3_can_do_amo_dup_for_tag_w_valid = (s3_req_miss_dup_for_tag_w_valid && !s3_req_probe_dup_for_tag_w_valid && s3_req_source_dup_for_tag_w_valid === AMO_SOURCE.U) ||
    s3_amo_hit_dup_for_tag_w_valid

  val s3_lr_dup_for_tag_w_valid = !s3_req_probe_dup_for_tag_w_valid && s3_req_source_dup_for_tag_w_valid === AMO_SOURCE.U && s3_req_cmd_dup_for_tag_w_valid === M_XLR
  val s3_sc_dup_for_tag_w_valid = !s3_req_probe_dup_for_tag_w_valid && s3_req_source_dup_for_tag_w_valid === AMO_SOURCE.U && s3_req_cmd_dup_for_tag_w_valid === M_XSC
  val lrsc_addr_dup_for_tag_w_valid = Reg(UInt())
  val lrsc_count_dup_for_tag_w_valid = RegInit(0.U(log2Ceil(LRSCCycles).W))

  when (s3_valid_dup_for_tag_w_valid && (s3_lr_dup_for_tag_w_valid || s3_sc_dup_for_tag_w_valid)) {
    when (s3_can_do_amo_dup_for_tag_w_valid && s3_lr_dup_for_tag_w_valid) {
      lrsc_count_dup_for_tag_w_valid := (LRSCCycles - 1).U
      lrsc_addr_dup_for_tag_w_valid := get_block_addr(s3_req_addr_dup_for_tag_w_valid)
    }.otherwise {
      lrsc_count_dup_for_tag_w_valid := 0.U
    }
  }.elsewhen (lrsc_count_dup_for_tag_w_valid > 0.U) {
    lrsc_count_dup_for_tag_w_valid := lrsc_count_dup_for_tag_w_valid - 1.U
  }

  val lrsc_valid_dup_for_tag_w_valid = lrsc_count_dup_for_tag_w_valid > LRSCBackOff.U
  val s3_lrsc_addr_match_dup_for_tag_w_valid = lrsc_valid_dup_for_tag_w_valid && lrsc_addr_dup_for_tag_w_valid === get_block_addr(s3_req_addr_dup_for_tag_w_valid)
  val s3_sc_fail_dup_for_tag_w_valid = s3_sc_dup_for_tag_w_valid && !s3_lrsc_addr_match_dup_for_tag_w_valid
  val s3_can_do_amo_write_dup_for_tag_w_valid = s3_can_do_amo_dup_for_tag_w_valid && isWrite(s3_req_cmd_dup_for_tag_w_valid) && !s3_sc_fail_dup_for_tag_w_valid
  val update_data_dup_for_tag_w_valid = s3_req_miss_dup_for_tag_w_valid || s3_store_hit_dup_for_tag_w_valid || s3_can_do_amo_write_dup_for_tag_w_valid

  val s3_probe_can_go_dup_for_tag_w_valid = s3_req_probe_dup_for_tag_w_valid &&
    io.wb_ready_dup(tagWritePort) &&
    (io.meta_write.ready || !probe_update_meta_dup_for_tag_w_valid)
  val s3_store_can_go_dup_for_tag_w_valid = s3_req_source_dup_for_tag_w_valid === STORE_SOURCE.U && !s3_req_probe_dup_for_tag_w_valid &&
    (io.meta_write.ready || !store_update_meta_dup_for_tag_w_valid) &&
    (io.data_write_ready_dup(tagWritePort) || !update_data_dup_for_tag_w_valid)
  val s3_amo_can_go_dup_for_tag_w_valid = s3_amo_hit_dup_for_tag_w_valid &&
    (io.meta_write.ready || !amo_update_meta_dup_for_tag_w_valid) &&
    (io.data_write_ready_dup(tagWritePort) || !update_data_dup_for_tag_w_valid) &&
    (s3_s_amoalu_dup_for_tag_w_valid || !amo_wait_amoalu_dup_for_tag_w_valid)
  val s3_miss_can_go_dup_for_tag_w_valid = s3_req_miss_dup_for_tag_w_valid &&
    (io.meta_write.ready || !amo_update_meta_dup_for_tag_w_valid) &&
    (io.data_write_ready_dup(tagWritePort) || !update_data_dup_for_tag_w_valid) &&
    (s3_s_amoalu_dup_for_tag_w_valid || !amo_wait_amoalu_dup_for_tag_w_valid) &&
    io.tag_write_ready_dup(tagWritePort) &&
    io.wb_ready_dup(tagWritePort)
  val s3_replace_can_go_dup_for_tag_w_valid = s3_req_replace_dup_for_tag_w_valid &&
    (s3_coh_dup_for_tag_w_valid.state === ClientStates.Nothing || io.wb_ready_dup(tagWritePort))
  val s3_can_go_dup_for_tag_w_valid = s3_probe_can_go_dup_for_tag_w_valid ||
    s3_store_can_go_dup_for_tag_w_valid ||
    s3_amo_can_go_dup_for_tag_w_valid ||
    s3_miss_can_go_dup_for_tag_w_valid ||
    s3_replace_can_go_dup_for_tag_w_valid

  val s3_fire_dup_for_tag_w_valid = s3_valid_dup_for_tag_w_valid && s3_can_go_dup_for_tag_w_valid
  when (do_amoalu_dup_for_tag_w_valid) { s3_s_amoalu_dup_for_tag_w_valid := true.B }
  when (s3_fire_dup_for_tag_w_valid) { s3_s_amoalu_dup_for_tag_w_valid := false.B }
  // -------------------------------------------------------------------------------------
  // ---------------- duplicate regs for data_write.valid to solve fanout ----------------
  val s3_req_miss_dup_for_data_w_valid = RegEnable(s2_req.miss, s2_fire_to_s3)
  val s3_req_probe_dup_for_data_w_valid = RegEnable(s2_req.probe, s2_fire_to_s3)
  val s3_tag_match_dup_for_data_w_valid = RegEnable(s2_tag_match, s2_fire_to_s3)
  val s3_coh_dup_for_data_w_valid = RegEnable(s2_coh, s2_fire_to_s3)
  val s3_req_probe_param_dup_for_data_w_valid = RegEnable(s2_req.probe_param, s2_fire_to_s3)
  val (_, _, probe_new_coh_dup_for_data_w_valid) = s3_coh_dup_for_data_w_valid.onProbe(s3_req_probe_param_dup_for_data_w_valid)
  val s3_req_source_dup_for_data_w_valid = RegEnable(s2_req.source, s2_fire_to_s3)
  val s3_req_cmd_dup_for_data_w_valid = RegEnable(s2_req.cmd, s2_fire_to_s3)
  val s3_req_replace_dup_for_data_w_valid = RegEnable(s2_req.replace, s2_fire_to_s3)
  val s3_hit_coh_dup_for_data_w_valid = RegEnable(s2_hit_coh, s2_fire_to_s3)
  val s3_new_hit_coh_dup_for_data_w_valid = RegEnable(s2_new_hit_coh, s2_fire_to_s3)
  
  val miss_update_meta_dup_for_data_w_valid = s3_req_miss_dup_for_data_w_valid
  val probe_update_meta_dup_for_data_w_valid = s3_req_probe_dup_for_data_w_valid && s3_tag_match_dup_for_data_w_valid && s3_coh_dup_for_data_w_valid =/= probe_new_coh_dup_for_data_w_valid
  val store_update_meta_dup_for_data_w_valid = s3_req_source_dup_for_data_w_valid === STORE_SOURCE.U &&
    !s3_req_probe_dup_for_data_w_valid &&
    s3_hit_coh_dup_for_data_w_valid =/= s3_new_hit_coh_dup_for_data_w_valid
  val amo_update_meta_dup_for_data_w_valid = s3_req_source_dup_for_data_w_valid === AMO_SOURCE.U &&
    !s3_req_probe_dup_for_data_w_valid &&
    s3_hit_coh_dup_for_data_w_valid =/= s3_new_hit_coh_dup_for_data_w_valid
  val update_meta_dup_for_data_w_valid = (
    miss_update_meta_dup_for_data_w_valid ||
    probe_update_meta_dup_for_data_w_valid ||
    store_update_meta_dup_for_data_w_valid ||
    amo_update_meta_dup_for_data_w_valid
  ) && !s3_req_replace_dup_for_data_w_valid

  val s3_valid_dup_for_data_w_valid = RegInit(false.B)
  val s3_amo_hit_dup_for_data_w_valid = RegEnable(s2_amo_hit, s2_fire_to_s3)
  val s3_s_amoalu_dup_for_data_w_valid = RegInit(false.B)
  val amo_wait_amoalu_dup_for_data_w_valid = s3_req_source_dup_for_data_w_valid === AMO_SOURCE.U &&
    s3_req_cmd_dup_for_data_w_valid =/= M_XLR &&
    s3_req_cmd_dup_for_data_w_valid =/= M_XSC
  val do_amoalu_dup_for_data_w_valid = amo_wait_amoalu_dup_for_data_w_valid && s3_valid_dup_for_data_w_valid && !s3_s_amoalu_dup_for_data_w_valid

  val s3_store_hit_dup_for_data_w_valid = RegEnable(s2_store_hit, s2_fire_to_s3)
  val s3_req_addr_dup_for_data_w_valid = RegEnable(s2_req.addr, s2_fire_to_s3)
  val s3_can_do_amo_dup_for_data_w_valid = (s3_req_miss_dup_for_data_w_valid && !s3_req_probe_dup_for_data_w_valid && s3_req_source_dup_for_data_w_valid === AMO_SOURCE.U) ||
    s3_amo_hit_dup_for_data_w_valid

  val s3_lr_dup_for_data_w_valid = !s3_req_probe_dup_for_data_w_valid && s3_req_source_dup_for_data_w_valid === AMO_SOURCE.U && s3_req_cmd_dup_for_data_w_valid === M_XLR
  val s3_sc_dup_for_data_w_valid = !s3_req_probe_dup_for_data_w_valid && s3_req_source_dup_for_data_w_valid === AMO_SOURCE.U && s3_req_cmd_dup_for_data_w_valid === M_XSC
  val lrsc_addr_dup_for_data_w_valid = Reg(UInt())
  val lrsc_count_dup_for_data_w_valid = RegInit(0.U(log2Ceil(LRSCCycles).W))

  when (s3_valid_dup_for_data_w_valid && (s3_lr_dup_for_data_w_valid || s3_sc_dup_for_data_w_valid)) {
    when (s3_can_do_amo_dup_for_data_w_valid && s3_lr_dup_for_data_w_valid) {
      lrsc_count_dup_for_data_w_valid := (LRSCCycles - 1).U
      lrsc_addr_dup_for_data_w_valid := get_block_addr(s3_req_addr_dup_for_data_w_valid)
    }.otherwise {
      lrsc_count_dup_for_data_w_valid := 0.U
    }
  }.elsewhen (lrsc_count_dup_for_data_w_valid > 0.U) {
    lrsc_count_dup_for_data_w_valid := lrsc_count_dup_for_data_w_valid - 1.U
  }

  val lrsc_valid_dup_for_data_w_valid = lrsc_count_dup_for_data_w_valid > LRSCBackOff.U
  val s3_lrsc_addr_match_dup_for_data_w_valid = lrsc_valid_dup_for_data_w_valid && lrsc_addr_dup_for_data_w_valid === get_block_addr(s3_req_addr_dup_for_data_w_valid)
  val s3_sc_fail_dup_for_data_w_valid = s3_sc_dup_for_data_w_valid && !s3_lrsc_addr_match_dup_for_data_w_valid
  val s3_can_do_amo_write_dup_for_data_w_valid = s3_can_do_amo_dup_for_data_w_valid && isWrite(s3_req_cmd_dup_for_data_w_valid) && !s3_sc_fail_dup_for_data_w_valid
  val update_data_dup_for_data_w_valid = s3_req_miss_dup_for_data_w_valid || s3_store_hit_dup_for_data_w_valid || s3_can_do_amo_write_dup_for_data_w_valid

  val s3_probe_can_go_dup_for_data_w_valid = s3_req_probe_dup_for_data_w_valid &&
    io.wb_ready_dup(dataWritePort) &&
    (io.meta_write.ready || !probe_update_meta_dup_for_data_w_valid)
  val s3_store_can_go_dup_for_data_w_valid = s3_req_source_dup_for_data_w_valid === STORE_SOURCE.U && !s3_req_probe_dup_for_data_w_valid &&
    (io.meta_write.ready || !store_update_meta_dup_for_data_w_valid) &&
    (io.data_write_ready_dup(dataWritePort) || !update_data_dup_for_data_w_valid)
  val s3_amo_can_go_dup_for_data_w_valid = s3_amo_hit_dup_for_data_w_valid &&
    (io.meta_write.ready || !amo_update_meta_dup_for_data_w_valid) &&
    (io.data_write_ready_dup(dataWritePort) || !update_data_dup_for_data_w_valid) &&
    (s3_s_amoalu_dup_for_data_w_valid || !amo_wait_amoalu_dup_for_data_w_valid)
  val s3_miss_can_go_dup_for_data_w_valid = s3_req_miss_dup_for_data_w_valid &&
    (io.meta_write.ready || !amo_update_meta_dup_for_data_w_valid) &&
    (io.data_write_ready_dup(dataWritePort) || !update_data_dup_for_data_w_valid) &&
    (s3_s_amoalu_dup_for_data_w_valid || !amo_wait_amoalu_dup_for_data_w_valid) &&
    io.tag_write_ready_dup(dataWritePort) &&
    io.wb_ready_dup(dataWritePort)
  val s3_replace_can_go_dup_for_data_w_valid = s3_req_replace_dup_for_data_w_valid &&
    (s3_coh_dup_for_data_w_valid.state === ClientStates.Nothing || io.wb_ready_dup(dataWritePort))
  val s3_can_go_dup_for_data_w_valid = s3_probe_can_go_dup_for_data_w_valid ||
    s3_store_can_go_dup_for_data_w_valid ||
    s3_amo_can_go_dup_for_data_w_valid ||
    s3_miss_can_go_dup_for_data_w_valid ||
    s3_replace_can_go_dup_for_data_w_valid
  val s3_update_data_cango_dup_for_data_w_valid = s3_store_can_go_dup_for_data_w_valid || s3_amo_can_go_dup_for_data_w_valid || s3_miss_can_go_dup_for_data_w_valid

  val s3_fire_dup_for_data_w_valid = s3_valid_dup_for_data_w_valid && s3_can_go_dup_for_data_w_valid
  when (do_amoalu_dup_for_data_w_valid) { s3_s_amoalu_dup_for_data_w_valid := true.B }
  when (s3_fire_dup_for_data_w_valid) { s3_s_amoalu_dup_for_data_w_valid := false.B }
1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064

  val s3_banked_store_wmask_dup_for_data_w_valid = RegEnable(s2_banked_store_wmask, s2_fire_to_s3)
  val s3_req_word_idx_dup_for_data_w_valid = RegEnable(s2_req.word_idx, s2_fire_to_s3)
  val banked_wmask = Mux(
    s3_req_miss_dup_for_data_w_valid,
    banked_full_wmask,
    Mux(
      s3_store_hit_dup_for_data_w_valid,
      s3_banked_store_wmask_dup_for_data_w_valid,
      Mux(
        s3_can_do_amo_write_dup_for_data_w_valid,
        UIntToOH(s3_req_word_idx_dup_for_data_w_valid),
        banked_none_wmask
      )
    )
  )
  assert(!(s3_valid && banked_wmask.orR && !update_data))

  val s3_sc_data_merged_dup_for_data_w_valid = Wire(Vec(DCacheBanks, UInt(DCacheSRAMRowBits.W)))
  val s3_req_amo_data_dup_for_data_w_valid = RegEnable(s2_req.amo_data, s2_fire_to_s3)
  val s3_req_amo_mask_dup_for_data_w_valid = RegEnable(s2_req.amo_mask, s2_fire_to_s3)
  for (i <- 0 until DCacheBanks) {
    val old_data = s3_store_data_merged(i)
    s3_sc_data_merged_dup_for_data_w_valid(i) := mergePutData(old_data, s3_req_amo_data_dup_for_data_w_valid,
      Mux(
        s3_req_word_idx_dup_for_data_w_valid === i.U && !s3_sc_fail_dup_for_data_w_valid,
        s3_req_amo_mask_dup_for_data_w_valid,
        0.U(wordBytes.W)
      )
    )
  }
1065 1066
  // -------------------------------------------------------------------------------------

Z
zhanglinjuan 已提交
1067
  val s3_fire = s3_valid_dup(4) && s3_can_go
Z
zhanglinjuan 已提交
1068 1069
  when (s2_fire_to_s3) {
    s3_valid := true.B
Z
zhanglinjuan 已提交
1070
    s3_valid_dup.foreach(_ := true.B)
1071 1072 1073 1074 1075
    s3_valid_dup_for_status.foreach(_ := true.B)
    s3_valid_dup_for_data_w_valid := true.B
    s3_valid_dup_for_meta_w_valid := true.B
    s3_valid_dup_for_err_w_valid := true.B
    s3_valid_dup_for_tag_w_valid := true.B
Z
zhanglinjuan 已提交
1076 1077
  }.elsewhen (s3_fire) {
    s3_valid := false.B
Z
zhanglinjuan 已提交
1078
    s3_valid_dup.foreach(_ := false.B)
1079 1080 1081 1082 1083
    s3_valid_dup_for_status.foreach(_ := false.B)
    s3_valid_dup_for_data_w_valid := false.B
    s3_valid_dup_for_meta_w_valid := false.B
    s3_valid_dup_for_err_w_valid := false.B
    s3_valid_dup_for_tag_w_valid := false.B
1084
  }
Z
zhanglinjuan 已提交
1085 1086 1087 1088
  s3_ready := !s3_valid_dup(5) || s3_can_go
  s3_s0_set_conflict := s3_valid_dup(6) && s3_idx_dup(0) === s0_idx
  s3_s0_set_conflict_store := s3_valid_dup(7) && s3_idx_dup(1) === store_idx
  assert(RegNext(!s3_valid || !(s3_req_source_dup_2 === STORE_SOURCE.U && !s3_req.probe) || s3_hit)) // miss store should never come to s3
Z
zhanglinjuan 已提交
1089

W
William Wang 已提交
1090 1091
  when(s3_fire) {
    s3_s_amoalu := false.B
Z
zhanglinjuan 已提交
1092
    s3_s_amoalu_dup.foreach(_ := false.B)
W
William Wang 已提交
1093
  }
Z
zhanglinjuan 已提交
1094 1095 1096 1097 1098

  req.ready := s0_can_go

  io.meta_read.valid := req.valid && s1_ready && !set_conflict
  io.meta_read.bits.idx := get_idx(s0_req.vaddr)
1099
  io.meta_read.bits.way_en := Mux(s0_req.replace, s0_req.replace_way_en, ~0.U(nWays.W))
Z
zhanglinjuan 已提交
1100

1101
  io.tag_read.valid := req.valid && s1_ready && !set_conflict && !s0_req.replace
Z
zhanglinjuan 已提交
1102 1103 1104
  io.tag_read.bits.idx := get_idx(s0_req.vaddr)
  io.tag_read.bits.way_en := ~0.U(nWays.W)

Z
zhanglinjuan 已提交
1105 1106
  io.data_read_intend := s1_valid_dup(3) && s1_need_data
  io.data_read.valid := s1_valid_dup(4) && s1_need_data && s2_ready
Z
zhanglinjuan 已提交
1107 1108
  io.data_read.bits.rmask := s1_banked_rmask
  io.data_read.bits.way_en := s1_way_en
Z
zhanglinjuan 已提交
1109
  io.data_read.bits.addr := s1_req_vaddr_dup_for_data_read
Z
zhanglinjuan 已提交
1110

Z
zhanglinjuan 已提交
1111
  io.miss_req.valid := s2_valid_dup(4) && s2_can_go_to_mq_dup(0)
W
William Wang 已提交
1112 1113 1114 1115 1116
  val miss_req = io.miss_req.bits
  miss_req := DontCare
  miss_req.source := s2_req.source
  miss_req.cmd := s2_req.cmd
  miss_req.addr := s2_req.addr
Z
zhanglinjuan 已提交
1117
  miss_req.vaddr := s2_req_vaddr_dup_for_miss_req
1118
  miss_req.way_en := Mux(s2_tag_match, s2_tag_match_way, s2_repl_way_en)
W
William Wang 已提交
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
  miss_req.store_data := s2_req.store_data
  miss_req.store_mask := s2_req.store_mask
  miss_req.word_idx := s2_req.word_idx
  miss_req.amo_data := s2_req.amo_data
  miss_req.amo_mask := s2_req.amo_mask
  miss_req.req_coh := s2_hit_coh
  miss_req.replace_coh := s2_repl_coh
  miss_req.replace_tag := s2_repl_tag
  miss_req.id := s2_req.id
  miss_req.cancel := false.B
Z
zhanglinjuan 已提交
1129

Z
zhanglinjuan 已提交
1130
  io.store_replay_resp.valid := s2_valid_dup(5) && s2_can_go_to_mq_dup(1) && replay && s2_req.isStore
Z
zhanglinjuan 已提交
1131 1132 1133 1134 1135
  io.store_replay_resp.bits.data := DontCare
  io.store_replay_resp.bits.miss := true.B
  io.store_replay_resp.bits.replay := true.B
  io.store_replay_resp.bits.id := s2_req.id

Z
zhanglinjuan 已提交
1136
  io.store_hit_resp.valid := s3_valid_dup(8) && s3_store_can_go
Z
zhanglinjuan 已提交
1137 1138 1139 1140 1141
  io.store_hit_resp.bits.data := DontCare
  io.store_hit_resp.bits.miss := false.B
  io.store_hit_resp.bits.replay := false.B
  io.store_hit_resp.bits.id := s3_req.id

Z
zhanglinjuan 已提交
1142 1143 1144
  io.release_update.valid := s3_valid_dup(9) && (s3_store_can_go || s3_amo_can_go) && s3_hit && update_data
  io.release_update.bits.addr := s3_req_addr_dup(3)
  io.release_update.bits.mask := Mux(s3_store_hit_dup(1), s3_banked_store_wmask, banked_amo_wmask)
W
William Wang 已提交
1145 1146 1147 1148 1149 1150 1151 1152 1153
  io.release_update.bits.data := Mux(
    amo_wait_amoalu, 
    s3_amo_data_merged_reg, 
    Mux(
      s3_sc,
      s3_sc_data_merged,
      s3_store_data_merged
    )
  ).asUInt
Z
zhanglinjuan 已提交
1154 1155 1156 1157 1158

  val atomic_hit_resp = Wire(new AtomicsResp)
  atomic_hit_resp.data := Mux(s3_sc, s3_sc_resp, s3_data_word)
  atomic_hit_resp.miss := false.B
  atomic_hit_resp.miss_id := s3_req.miss_id
1159
  atomic_hit_resp.error := s3_error
Z
zhanglinjuan 已提交
1160
  atomic_hit_resp.replay := false.B
Z
zhanglinjuan 已提交
1161 1162
  atomic_hit_resp.ack_miss_queue := s3_req_miss_dup(5)
  atomic_hit_resp.id := lrsc_valid_dup(2)
Z
zhanglinjuan 已提交
1163 1164 1165 1166
  val atomic_replay_resp = Wire(new AtomicsResp)
  atomic_replay_resp.data := DontCare
  atomic_replay_resp.miss := true.B
  atomic_replay_resp.miss_id := DontCare
1167
  atomic_replay_resp.error := false.B
Z
zhanglinjuan 已提交
1168 1169 1170
  atomic_replay_resp.replay := true.B
  atomic_replay_resp.ack_miss_queue := false.B
  atomic_replay_resp.id := DontCare
Z
zhanglinjuan 已提交
1171 1172
  val atomic_replay_resp_valid = s2_valid_dup(6) && s2_can_go_to_mq_dup(2) && replay && s2_req.isAMO
  val atomic_hit_resp_valid = s3_valid_dup(10) && (s3_amo_can_go || s3_miss_can_go && s3_req.isAMO)
Z
zhanglinjuan 已提交
1173 1174
  io.atomic_resp.valid := atomic_replay_resp_valid || atomic_hit_resp_valid
  io.atomic_resp.bits := Mux(atomic_replay_resp_valid, atomic_replay_resp, atomic_hit_resp)
1175

Z
zhanglinjuan 已提交
1176
  io.replace_resp.valid := s3_fire && s3_req_replace_dup(3)
1177 1178
  io.replace_resp.bits := s3_req.miss_id

1179
  io.meta_write.valid := s3_fire_dup_for_meta_w_valid && update_meta_dup_for_meta_w_valid
Z
zhanglinjuan 已提交
1180 1181
  io.meta_write.bits.idx := s3_idx_dup(2)
  io.meta_write.bits.way_en := s3_way_en_dup(0)
Z
zhanglinjuan 已提交
1182 1183
  io.meta_write.bits.meta.coh := new_coh

1184
  io.error_flag_write.valid := s3_fire_dup_for_err_w_valid && update_meta_dup_for_err_w_valid && s3_l2_error
Z
zhanglinjuan 已提交
1185 1186
  io.error_flag_write.bits.idx := s3_idx_dup(3)
  io.error_flag_write.bits.way_en := s3_way_en_dup(1)
1187
  io.error_flag_write.bits.error := s3_l2_error
1188

1189
  io.tag_write.valid := s3_fire_dup_for_tag_w_valid && s3_req_miss_dup_for_tag_w_valid
Z
zhanglinjuan 已提交
1190 1191 1192
  io.tag_write.bits.idx := s3_idx_dup(4)
  io.tag_write.bits.way_en := s3_way_en_dup(2)
  io.tag_write.bits.tag := get_tag(s3_req_addr_dup(4))
Z
zhanglinjuan 已提交
1193

Z
zhanglinjuan 已提交
1194
  io.tag_write_intend := s3_req_miss_dup(7) && s3_valid_dup(11)
1195 1196 1197 1198 1199
  XSPerfAccumulate("fake_tag_write_intend", io.tag_write_intend && !io.tag_write.valid)
  XSPerfAccumulate("mainpipe_tag_write", io.tag_write.valid)

  assert(!RegNext(io.tag_write.valid && !io.tag_write_intend))

1200
  io.data_write.valid := s3_valid_dup_for_data_w_valid && s3_update_data_cango_dup_for_data_w_valid && update_data_dup_for_data_w_valid
Z
zhanglinjuan 已提交
1201 1202
  io.data_write.bits.way_en := s3_way_en_dup(3)
  io.data_write.bits.addr := s3_req_vaddr_dup_for_data_write
Z
zhanglinjuan 已提交
1203
  io.data_write.bits.wmask := banked_wmask
W
William Wang 已提交
1204
  io.data_write.bits.data := Mux(
1205
    amo_wait_amoalu_dup_for_data_w_valid, 
W
William Wang 已提交
1206 1207
    s3_amo_data_merged_reg, 
    Mux(
1208 1209
      s3_sc_dup_for_data_w_valid,
      s3_sc_data_merged_dup_for_data_w_valid,
W
William Wang 已提交
1210 1211 1212
      s3_store_data_merged
    )
  )
1213 1214 1215
  assert(RegNext(!io.meta_write.valid || !s3_req.replace))
  assert(RegNext(!io.tag_write.valid || !s3_req.replace))
  assert(RegNext(!io.data_write.valid || !s3_req.replace))
Z
zhanglinjuan 已提交
1216

Z
zhanglinjuan 已提交
1217
  io.wb.valid := s3_valid_dup(13) && (
1218
    // replace
Z
zhanglinjuan 已提交
1219
    s3_req_replace_dup(4) && !s3_replace_nothing ||
Z
zhanglinjuan 已提交
1220
    // probe can go to wbq
Z
zhanglinjuan 已提交
1221
    s3_req_probe_dup(9) && (io.meta_write.ready || !probe_update_meta) ||
Z
zhanglinjuan 已提交
1222
      // amo miss can go to wbq
Z
zhanglinjuan 已提交
1223
      s3_req_miss_dup(8) &&
Z
zhanglinjuan 已提交
1224 1225
        (io.meta_write.ready || !amo_update_meta) &&
        (io.data_write.ready || !update_data) &&
Z
zhanglinjuan 已提交
1226
        (s3_s_amoalu_dup(2) || !amo_wait_amoalu) &&
Z
zhanglinjuan 已提交
1227 1228
        io.tag_write.ready
    ) && need_wb
Z
zhanglinjuan 已提交
1229

Z
zhanglinjuan 已提交
1230 1231
  io.wb.bits.addr := get_block_addr(Cat(s3_tag, get_untag(s3_req.vaddr)))
  io.wb.bits.param := writeback_param
Z
zhanglinjuan 已提交
1232
  io.wb.bits.voluntary := s3_req_miss_dup(9) || s3_req_replace_dup(5)
Z
zhanglinjuan 已提交
1233
  io.wb.bits.hasData := writeback_data
Z
zhanglinjuan 已提交
1234
  io.wb.bits.dirty := s3_coh_dup(5) === ClientStates.Dirty
Z
zhanglinjuan 已提交
1235
  io.wb.bits.data := s3_data.asUInt()
Z
zhanglinjuan 已提交
1236
  io.wb.bits.delay_release := s3_req_replace_dup(6)
1237
  io.wb.bits.miss_id := s3_req.miss_id
Z
zhanglinjuan 已提交
1238

1239
  io.replace_access.valid := RegNext(s1_fire && (s1_req.isAMO || s1_req.isStore) && !s1_req.probe)
Z
zhanglinjuan 已提交
1240
  io.replace_access.bits.set := s2_idx_dup_for_replace_access
Z
zhanglinjuan 已提交
1241 1242 1243
  io.replace_access.bits.way := RegNext(OHToUInt(s1_way_en))

  io.replace_way.set.valid := RegNext(s0_fire)
Z
zhanglinjuan 已提交
1244
  io.replace_way.set.bits := s1_idx_dup_for_replace_way
Z
zhanglinjuan 已提交
1245 1246 1247 1248

  // TODO: consider block policy of a finer granularity
  io.status.s0_set.valid := req.valid
  io.status.s0_set.bits := get_idx(s0_req.vaddr)
Z
zhanglinjuan 已提交
1249
  io.status.s1.valid := s1_valid_dup(5)
1250
  io.status.s1.bits.set := s1_idx
Z
zhanglinjuan 已提交
1251
  io.status.s1.bits.way_en := s1_way_en
Z
zhanglinjuan 已提交
1252 1253
  io.status.s2.valid := s2_valid_dup(7) && !s2_req_replace_dup_2
  io.status.s2.bits.set := s2_idx_dup_for_status
Z
zhanglinjuan 已提交
1254
  io.status.s2.bits.way_en := s2_way_en
Z
zhanglinjuan 已提交
1255 1256
  io.status.s3.valid := s3_valid && !s3_req_replace_dup(7)
  io.status.s3.bits.set := s3_idx_dup(5)
Z
zhanglinjuan 已提交
1257
  io.status.s3.bits.way_en := s3_way_en
1258

1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271
  for ((s, i) <- io.status_dup.zipWithIndex) {
    s.s1.valid := s1_valid_dup_for_status(i)
    s.s1.bits.set := RegEnable(get_idx(s0_req.vaddr), s0_fire)
    s.s1.bits.way_en := s1_way_en
    s.s2.valid := s2_valid_dup_for_status(i) && !RegEnable(s1_req.replace, s1_fire)
    s.s2.bits.set := RegEnable(get_idx(s1_req.vaddr), s1_fire)
    s.s2.bits.way_en := RegEnable(s1_way_en, s1_fire)
    s.s3.valid := s3_valid_dup_for_status(i) && !RegEnable(s2_req.replace, s2_fire_to_s3)
    s.s3.bits.set := RegEnable(get_idx(s2_req.vaddr), s2_fire_to_s3)
    s.s3.bits.way_en := RegEnable(s2_way_en, s2_fire_to_s3)
  }
  dontTouch(io.status_dup)

1272
  // report error to beu and csr, 1 cycle after read data resp
1273
  io.error := 0.U.asTypeOf(new L1CacheErrorInfo())
1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
  // report error, update error csr
  io.error.valid := s3_error && RegNext(s2_fire)
  // only tag_error and data_error will be reported to beu
  // l2_error should not be reported (l2 will report that) 
  io.error.report_to_beu := (RegEnable(s2_tag_error, s2_fire) || s3_data_error) && RegNext(s2_fire)
  io.error.paddr := RegEnable(s2_req.addr, s2_fire)
  io.error.source.tag := RegEnable(s2_tag_error, s2_fire)
  io.error.source.data := s3_data_error
  io.error.source.l2 := RegEnable(s2_flag_error || s2_l2_error, s2_fire)
  io.error.opType.store := RegEnable(s2_req.isStore && !s2_req.probe, s2_fire)
  io.error.opType.probe := RegEnable(s2_req.probe, s2_fire)
  io.error.opType.release := RegEnable(s2_req.replace, s2_fire)
  io.error.opType.atom := RegEnable(s2_req.isAMO && !s2_req.probe, s2_fire)
1287

1288
  val perfEvents = Seq(
1289 1290
    ("dcache_mp_req          ", s0_fire                                                      ),
    ("dcache_mp_total_penalty", PopCount(VecInit(Seq(s0_fire, s1_valid, s2_valid, s3_valid))))
1291
  )
1292
  generatePerfEvent()
1293
}