xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/loadpipe/LoadPipe.scala (revision 51f9a957bed418a09ee0e36f827174ce8ef2ac8e)
11f0e2dc7SJiawei Lin/***************************************************************************************
21f0e2dc7SJiawei Lin* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
31f0e2dc7SJiawei Lin* Copyright (c) 2020-2021 Peng Cheng Laboratory
41f0e2dc7SJiawei Lin*
51f0e2dc7SJiawei Lin* XiangShan is licensed under Mulan PSL v2.
61f0e2dc7SJiawei Lin* You can use this software according to the terms and conditions of the Mulan PSL v2.
71f0e2dc7SJiawei Lin* You may obtain a copy of Mulan PSL v2 at:
81f0e2dc7SJiawei Lin*          http://license.coscl.org.cn/MulanPSL2
91f0e2dc7SJiawei Lin*
101f0e2dc7SJiawei Lin* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
111f0e2dc7SJiawei Lin* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
121f0e2dc7SJiawei Lin* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
131f0e2dc7SJiawei Lin*
141f0e2dc7SJiawei Lin* See the Mulan PSL v2 for more details.
151f0e2dc7SJiawei Lin***************************************************************************************/
161f0e2dc7SJiawei Lin
171f0e2dc7SJiawei Linpackage xiangshan.cache
181f0e2dc7SJiawei Lin
198891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters
201f0e2dc7SJiawei Linimport chisel3._
211f0e2dc7SJiawei Linimport chisel3.util._
221f0e2dc7SJiawei Linimport freechips.rocketchip.tilelink.ClientMetadata
2344f2941bSJiru Sunimport utility.{ParallelPriorityMux, OneHot, ChiselDB, ParallelORR, ParallelMux, XSDebug, XSPerfAccumulate, HasPerfEvents}
240d32f713Shappy-lximport xiangshan.{XSCoreParamsKey, L1CacheErrorInfo}
2504665835SMaxpicca-Liimport xiangshan.cache.wpu._
260d32f713Shappy-lximport xiangshan.mem.HasL1PrefetchSourceParameter
270d32f713Shappy-lximport xiangshan.mem.prefetch._
28d2945707SHuijin Liimport xiangshan.mem.LqPtr
291f0e2dc7SJiawei Lin
300d32f713Shappy-lxclass LoadPfDbBundle(implicit p: Parameters) extends DCacheBundle {
310d32f713Shappy-lx  val paddr = UInt(PAddrBits.W)
320d32f713Shappy-lx}
330d32f713Shappy-lx
340d32f713Shappy-lxclass LoadPipe(id: Int)(implicit p: Parameters) extends DCacheModule with HasPerfEvents with HasL1PrefetchSourceParameter {
351f0e2dc7SJiawei Lin  val io = IO(new DCacheBundle {
361f0e2dc7SJiawei Lin    // incoming requests
371f0e2dc7SJiawei Lin    val lsu = Flipped(new DCacheLoadIO)
3804665835SMaxpicca-Li    val dwpu = Flipped(new DwpuBaseIO(nWays = nWays, nPorts = 1))
39cdbff57cSHaoyuan Feng    val load128Req = Input(Bool())
401f0e2dc7SJiawei Lin    // req got nacked in stage 0?
411f0e2dc7SJiawei Lin    val nack      = Input(Bool())
421f0e2dc7SJiawei Lin
431f0e2dc7SJiawei Lin    // meta and data array read port
44ad3ba452Szhanglinjuan    val meta_read = DecoupledIO(new MetaReadReq)
4541b68474SWilliam Wang    val meta_resp = Input(Vec(nWays, new Meta))
463af6aa6eSWilliam Wang    val extra_meta_resp = Input(Vec(nWays, new DCacheExtraMeta))
47ad3ba452Szhanglinjuan
48ad3ba452Szhanglinjuan    val tag_read = DecoupledIO(new TagReadReq)
4941b68474SWilliam Wang    val tag_resp = Input(Vec(nWays, UInt(encTagBits.W)))
5004665835SMaxpicca-Li    val vtag_update = Flipped(DecoupledIO(new TagWriteReq))
51ad3ba452Szhanglinjuan
52cdbff57cSHaoyuan Feng    val banked_data_read = DecoupledIO(new L1BankedDataReadReqWithMask)
53cdbff57cSHaoyuan Feng    val is128Req = Output(Bool())
54cdbff57cSHaoyuan Feng    val banked_data_resp = Input(Vec(VLEN/DCacheSRAMRowBits, new L1BankedDataReadResult()))
55cdbff57cSHaoyuan Feng    val read_error_delayed = Input(Vec(VLEN/DCacheSRAMRowBits, Bool()))
561f0e2dc7SJiawei Lin
573af6aa6eSWilliam Wang    // access bit update
583af6aa6eSWilliam Wang    val access_flag_write = DecoupledIO(new FlagMetaWriteReq)
590d32f713Shappy-lx    val prefetch_flag_write = DecoupledIO(new SourceMetaWriteReq)
603af6aa6eSWilliam Wang
611f0e2dc7SJiawei Lin    // banked data read conflict
621f0e2dc7SJiawei Lin    val bank_conflict_slow = Input(Bool())
631f0e2dc7SJiawei Lin
641f0e2dc7SJiawei Lin    // send miss request to miss queue
651f0e2dc7SJiawei Lin    val miss_req    = DecoupledIO(new MissReq)
66683c1411Shappy-lx    val miss_resp   = Input(new MissResp)
671f0e2dc7SJiawei Lin
6808b0bc30Shappy-lx    // send miss request to wbq
6908b0bc30Shappy-lx    val wbq_conflict_check = Valid(UInt())
7008b0bc30Shappy-lx    val wbq_block_miss_req = Input(Bool())
7108b0bc30Shappy-lx
721f0e2dc7SJiawei Lin    // update state vec in replacement algo
731f0e2dc7SJiawei Lin    val replace_access = ValidIO(new ReplacementAccessBundle)
74ad3ba452Szhanglinjuan    // find the way to be replaced
75ad3ba452Szhanglinjuan    val replace_way = new ReplacementWayReqIO
761f0e2dc7SJiawei Lin
771f0e2dc7SJiawei Lin    // load fast wakeup should be disabled when data read is not ready
781f0e2dc7SJiawei Lin    val disable_ld_fast_wakeup = Input(Bool())
79dd95524eSzhanglinjuan
80dd95524eSzhanglinjuan    // ecc error
810184a80eSYanqin Li    val error = Output(ValidIO(new L1CacheErrorInfo))
8272dab974Scz4e    val pseudo_error = Flipped(DecoupledIO(Vec(DCacheBanks, new CtrlUnitSignalingBundle)))
8372dab974Scz4e    val pseudo_tag_error_inj_done = Output(Bool())
8472dab974Scz4e    val pseudo_data_error_inj_done = Output(Bool())
858744445eSMaxpicca-Li
860d32f713Shappy-lx    val prefetch_info = new Bundle {
870d32f713Shappy-lx      val naive = new Bundle {
880d32f713Shappy-lx        val total_prefetch = Output(Bool())
890d32f713Shappy-lx        val late_hit_prefetch = Output(Bool())
900d32f713Shappy-lx        val late_prefetch_hit = Output(Bool())
910d32f713Shappy-lx        val late_load_hit = Output(Bool())
920d32f713Shappy-lx        val useless_prefetch = Output(Bool())
930d32f713Shappy-lx        val useful_prefetch = Output(Bool())
940d32f713Shappy-lx        val prefetch_hit = Output(Bool())
950d32f713Shappy-lx      }
960d32f713Shappy-lx
970d32f713Shappy-lx      val fdp = new Bundle {
980d32f713Shappy-lx        val useful_prefetch = Output(Bool())
990d32f713Shappy-lx        val demand_miss = Output(Bool())
1000d32f713Shappy-lx        val pollution = Output(Bool())
1010d32f713Shappy-lx      }
1020d32f713Shappy-lx    }
1030d32f713Shappy-lx
1040d32f713Shappy-lx    val bloom_filter_query = new Bundle {
1050d32f713Shappy-lx      val query = ValidIO(new BloomQueryBundle(BLOOM_FILTER_ENTRY_NUM))
1060d32f713Shappy-lx      val resp = Flipped(ValidIO(new BloomRespBundle()))
1070d32f713Shappy-lx    }
1080d32f713Shappy-lx
1090d32f713Shappy-lx    val counter_filter_query = new CounterFilterQueryBundle
1100d32f713Shappy-lx    val counter_filter_enq = new ValidIO(new CounterFilterDataBundle())
1111f0e2dc7SJiawei Lin  })
1121f0e2dc7SJiawei Lin
113ad3ba452Szhanglinjuan  assert(RegNext(io.meta_read.ready))
114ad3ba452Szhanglinjuan
1151f0e2dc7SJiawei Lin  val s1_ready = Wire(Bool())
1161f0e2dc7SJiawei Lin  val s2_ready = Wire(Bool())
1171f0e2dc7SJiawei Lin  // LSU requests
1181f0e2dc7SJiawei Lin  // it you got nacked, you can directly passdown
119ad3ba452Szhanglinjuan  val not_nacked_ready = io.meta_read.ready && io.tag_read.ready && s1_ready
1201f0e2dc7SJiawei Lin  val nacked_ready     = true.B
1211f0e2dc7SJiawei Lin
1221f0e2dc7SJiawei Lin  // Pipeline
1231f0e2dc7SJiawei Lin  // --------------------------------------------------------------------------------
1241f0e2dc7SJiawei Lin  // stage 0
1256786cfb7SWilliam Wang  // --------------------------------------------------------------------------------
1266786cfb7SWilliam Wang  // read tag
1276786cfb7SWilliam Wang
12804665835SMaxpicca-Li  // ready can wait for valid
12904665835SMaxpicca-Li  io.lsu.req.ready := (!io.nack && not_nacked_ready) || (io.nack && nacked_ready)
130935edac4STang Haojin  io.meta_read.valid := io.lsu.req.fire && !io.nack
131935edac4STang Haojin  io.tag_read.valid := io.lsu.req.fire && !io.nack
13204665835SMaxpicca-Li
133935edac4STang Haojin  val s0_valid = io.lsu.req.fire
1346a539f6dSAnzooooo  val s0_req = WireInit(io.lsu.req.bits)
1356a539f6dSAnzooooo  s0_req.vaddr := Mux(io.load128Req, Cat(io.lsu.req.bits.vaddr(io.lsu.req.bits.vaddr.getWidth - 1, 4), 0.U(4.W)), io.lsu.req.bits.vaddr)
1361f0e2dc7SJiawei Lin  val s0_fire = s0_valid && s1_ready
137d2b20d1aSTang Haojin  val s0_vaddr = s0_req.vaddr
138144422dcSMaxpicca-Li  val s0_replayCarry = s0_req.replayCarry
139cdbff57cSHaoyuan Feng  val s0_load128Req = io.load128Req
140cdbff57cSHaoyuan Feng  val s0_bank_oh_64 = UIntToOH(addr_to_dcache_bank(s0_vaddr))
141cdbff57cSHaoyuan Feng  val s0_bank_oh_128 = (s0_bank_oh_64 << 1.U).asUInt | s0_bank_oh_64.asUInt
142cdbff57cSHaoyuan Feng  val s0_bank_oh = Mux(s0_load128Req, s0_bank_oh_128, s0_bank_oh_64)
1433f4ec46fSCODE-JTZ  assert(RegNext(!(s0_valid && (s0_req.cmd =/= MemoryOpConstants.M_XRD && s0_req.cmd =/= MemoryOpConstants.M_PFR && s0_req.cmd =/= MemoryOpConstants.M_PFW))), "LoadPipe only accepts load req / softprefetch read or write!")
1441f0e2dc7SJiawei Lin  dump_pipeline_reqs("LoadPipe s0", s0_valid, s0_req)
1451f0e2dc7SJiawei Lin
14604665835SMaxpicca-Li  // wpu
14704665835SMaxpicca-Li  // val dwpu = Module(new DCacheWpuWrapper)
14804665835SMaxpicca-Li  // req in s0
14904665835SMaxpicca-Li  if(dwpuParam.enWPU){
15004665835SMaxpicca-Li    io.dwpu.req(0).bits.vaddr := s0_vaddr
15104665835SMaxpicca-Li    io.dwpu.req(0).bits.replayCarry := s0_replayCarry
15204665835SMaxpicca-Li    io.dwpu.req(0).valid := s0_valid
15304665835SMaxpicca-Li  }else{
15404665835SMaxpicca-Li    io.dwpu.req(0).valid := false.B
15504665835SMaxpicca-Li    io.dwpu.req(0).bits := DontCare
15604665835SMaxpicca-Li  }
15704665835SMaxpicca-Li
15804665835SMaxpicca-Li
15904665835SMaxpicca-Li  val meta_read = io.meta_read.bits
16004665835SMaxpicca-Li  val tag_read = io.tag_read.bits
16104665835SMaxpicca-Li
16204665835SMaxpicca-Li  // Tag read for new requests
16304665835SMaxpicca-Li  meta_read.idx := get_idx(io.lsu.req.bits.vaddr)
16404665835SMaxpicca-Li  meta_read.way_en := ~0.U(nWays.W)
16504665835SMaxpicca-Li  // meta_read.tag := DontCare
16604665835SMaxpicca-Li
16704665835SMaxpicca-Li  tag_read.idx := get_idx(io.lsu.req.bits.vaddr)
16804665835SMaxpicca-Li  tag_read.way_en := ~0.U(nWays.W)
16904665835SMaxpicca-Li
1701f0e2dc7SJiawei Lin  // --------------------------------------------------------------------------------
1711f0e2dc7SJiawei Lin  // stage 1
1726786cfb7SWilliam Wang  // --------------------------------------------------------------------------------
1736786cfb7SWilliam Wang  // tag match, read data
1746786cfb7SWilliam Wang
1751f0e2dc7SJiawei Lin  val s1_valid = RegInit(false.B)
1761f0e2dc7SJiawei Lin  val s1_req = RegEnable(s0_req, s0_fire)
1771f0e2dc7SJiawei Lin  // in stage 1, load unit gets the physical address
17803efd994Shappy-lx  val s1_paddr_dup_lsu = io.lsu.s1_paddr_dup_lsu
17903efd994Shappy-lx  val s1_paddr_dup_dcache = io.lsu.s1_paddr_dup_dcache
180cdbff57cSHaoyuan Feng  val s1_load128Req = RegEnable(s0_load128Req, s0_fire)
18120e09ab1Shappy-lx  val s1_is_prefetch = s1_req.instrtype === DCACHE_PREFETCH_SOURCE.U
182c3b763d0SYinan Xu  // LSU may update the address from io.lsu.s1_paddr, which affects the bank read enable only.
1836a539f6dSAnzooooo  val s1_vaddr_update = Cat(s1_req.vaddr(VAddrBits - 1, blockOffBits), io.lsu.s1_paddr_dup_lsu(blockOffBits - 1, 0))
184fa5e530dScz4e  val s1_vaddr_update_dup = Cat(s1_req.vaddr_dup(VAddrBits - 1, blockOffBits), io.lsu.s1_paddr_dup_dcache(blockOffBits - 1, 0))
1856a539f6dSAnzooooo  val s1_vaddr = Mux(s1_load128Req, Cat(s1_vaddr_update(VAddrBits - 1, 4), 0.U(4.W)), s1_vaddr_update)
186fa5e530dScz4e  val s1_vaddr_dup = Mux(s1_load128Req, Cat(s1_vaddr_update_dup(VAddrBits - 1, 4), 0.U(4.W)), s1_vaddr_update_dup)
187cdbff57cSHaoyuan Feng  val s1_bank_oh = RegEnable(s0_bank_oh, s0_fire)
1881f0e2dc7SJiawei Lin  val s1_nack = RegNext(io.nack)
1891f0e2dc7SJiawei Lin  val s1_fire = s1_valid && s2_ready
1901f0e2dc7SJiawei Lin  s1_ready := !s1_valid || s1_fire
1911f0e2dc7SJiawei Lin
1921f0e2dc7SJiawei Lin  when (s0_fire) { s1_valid := true.B }
1931f0e2dc7SJiawei Lin  .elsewhen (s1_fire) { s1_valid := false.B }
1941f0e2dc7SJiawei Lin
1951f0e2dc7SJiawei Lin  dump_pipeline_reqs("LoadPipe s1", s1_valid, s1_req)
1961f0e2dc7SJiawei Lin
1971f0e2dc7SJiawei Lin  // tag check
1981f0e2dc7SJiawei Lin  def wayMap[T <: Data](f: Int => T) = VecInit((0 until nWays).map(f))
19972dab974Scz4e  val meta_resp = io.meta_resp
20072dab974Scz4e  // pseudo enc ecc tag
20172dab974Scz4e  val pseudo_tag_toggle_mask = Mux(
20272dab974Scz4e                                io.pseudo_error.valid && io.pseudo_error.bits(0).valid,
20372dab974Scz4e                                io.pseudo_error.bits(0).mask(tagBits - 1, 0),
20472dab974Scz4e                                0.U(tagBits.W)
20572dab974Scz4e                            )
20672dab974Scz4e  val s1_enctag_resp = Wire(io.tag_resp.cloneType)
20772dab974Scz4e  s1_enctag_resp.zip(io.tag_resp).map {
20872dab974Scz4e    case (pseudo_enc, real_enc) =>
20972dab974Scz4e    if (cacheCtrlParamsOpt.nonEmpty && EnableTagEcc) {
21072dab974Scz4e      val ecc = real_enc(encTagBits - 1, tagBits)
21172dab974Scz4e      val toggleTag = real_enc(tagBits - 1, 0) ^ pseudo_tag_toggle_mask
21272dab974Scz4e      pseudo_enc := Cat(ecc, toggleTag)
21372dab974Scz4e    }  else {
21472dab974Scz4e      pseudo_enc := real_enc
21572dab974Scz4e    }
21672dab974Scz4e  }
21703efd994Shappy-lx
218144422dcSMaxpicca-Li  // resp in s1
21972dab974Scz4e  val s1_tag_resp = s1_enctag_resp.map(encTag => encTag(tagBits - 1, 0))
22072dab974Scz4e  val s1_tag_errors = wayMap((w: Int) => meta_resp(w).coh.isValid() && dcacheParameters.tagCode.decode(s1_enctag_resp(w)).error).asUInt
22172dab974Scz4e  val s1_tag_match_way_dup_dc = wayMap((w: Int) => s1_tag_resp(w) === get_tag(s1_paddr_dup_dcache) && meta_resp(w).coh.isValid()).asUInt
22272dab974Scz4e  val s1_tag_match_way_dup_lsu = wayMap((w: Int) => s1_tag_resp(w) === get_tag(s1_paddr_dup_lsu) && meta_resp(w).coh.isValid()).asUInt
22304665835SMaxpicca-Li  val s1_wpu_pred_valid = RegEnable(io.dwpu.resp(0).valid, s0_fire)
22404665835SMaxpicca-Li  val s1_wpu_pred_way_en = RegEnable(io.dwpu.resp(0).bits.s0_pred_way_en, s0_fire)
22527dc8a4dSWilliam Wang
22604665835SMaxpicca-Li  // lookup update
22704665835SMaxpicca-Li  io.dwpu.lookup_upd(0).valid := s1_valid
22804665835SMaxpicca-Li  io.dwpu.lookup_upd(0).bits.vaddr := s1_vaddr
22904665835SMaxpicca-Li  io.dwpu.lookup_upd(0).bits.s1_real_way_en := s1_tag_match_way_dup_dc
23004665835SMaxpicca-Li  io.dwpu.lookup_upd(0).bits.s1_pred_way_en := s1_wpu_pred_way_en
23104665835SMaxpicca-Li  // replace / tag write
23204665835SMaxpicca-Li  io.vtag_update.ready := true.B
23304665835SMaxpicca-Li  // dwpu.io.tagwrite_upd.valid := io.vtag_update.valid
23404665835SMaxpicca-Li  // dwpu.io.tagwrite_upd.bits.vaddr := io.vtag_update.bits.vaddr
23504665835SMaxpicca-Li  // dwpu.io.tagwrite_upd.bits.s1_real_way_en := io.vtag_update.bits.way_en
23604665835SMaxpicca-Li
23704665835SMaxpicca-Li  val s1_direct_map_way_num = get_direct_map_way(s1_req.vaddr)
23804665835SMaxpicca-Li  if(dwpuParam.enCfPred || !env.FPGAPlatform){
23904665835SMaxpicca-Li    /* method1: record the pc */
24004665835SMaxpicca-Li    // if (!env.FPGAPlatform){
24104665835SMaxpicca-Li    //    io.dwpu.cfpred(0).s0_vaddr := io.lsu.s0_pc
24204665835SMaxpicca-Li    //    io.dwpu.cfpred(0).s1_vaddr := io.lsu.s1_pc
24304665835SMaxpicca-Li    // }
24404665835SMaxpicca-Li
24504665835SMaxpicca-Li    /* method2: record the vaddr */
24604665835SMaxpicca-Li    io.dwpu.cfpred(0).s0_vaddr := s0_vaddr
24704665835SMaxpicca-Li    io.dwpu.cfpred(0).s1_vaddr := s1_vaddr
24804665835SMaxpicca-Li    // whether direct_map_way miss with valid tag value
24972dab974Scz4e    io.dwpu.cfpred(0).s1_dm_hit := wayMap((w: Int) => w.U === s1_direct_map_way_num && s1_tag_resp(w) === get_tag(s1_paddr_dup_lsu) && meta_resp(w).coh.isValid()).asUInt.orR
25004665835SMaxpicca-Li  }else{
25104665835SMaxpicca-Li    io.dwpu.cfpred(0) := DontCare
252144422dcSMaxpicca-Li  }
25304665835SMaxpicca-Li
25404665835SMaxpicca-Li  val s1_pred_tag_match_way_dup_dc = Wire(UInt(nWays.W))
25504665835SMaxpicca-Li  val s1_wpu_pred_fail = Wire(Bool())
25604665835SMaxpicca-Li  val s1_wpu_pred_fail_and_real_hit = Wire(Bool())
25704665835SMaxpicca-Li  if (dwpuParam.enWPU) {
25804665835SMaxpicca-Li    when(s1_wpu_pred_valid) {
25904665835SMaxpicca-Li      s1_pred_tag_match_way_dup_dc := s1_wpu_pred_way_en
26004665835SMaxpicca-Li    }.otherwise {
26104665835SMaxpicca-Li      s1_pred_tag_match_way_dup_dc := s1_tag_match_way_dup_dc
26204665835SMaxpicca-Li    }
26304665835SMaxpicca-Li    s1_wpu_pred_fail := s1_valid && s1_tag_match_way_dup_dc =/= s1_pred_tag_match_way_dup_dc
26404665835SMaxpicca-Li    s1_wpu_pred_fail_and_real_hit := s1_wpu_pred_fail && s1_tag_match_way_dup_dc.orR
26504665835SMaxpicca-Li  } else {
26604665835SMaxpicca-Li    s1_pred_tag_match_way_dup_dc := s1_tag_match_way_dup_dc
26704665835SMaxpicca-Li    s1_wpu_pred_fail := false.B
26804665835SMaxpicca-Li    s1_wpu_pred_fail_and_real_hit := false.B
26904665835SMaxpicca-Li  }
27004665835SMaxpicca-Li
271cd2ff98bShappy-lx  val s1_tag_match_dup_dc = ParallelORR(s1_tag_match_way_dup_dc)
272cd2ff98bShappy-lx  val s1_tag_match_dup_lsu = ParallelORR(s1_tag_match_way_dup_lsu)
273144422dcSMaxpicca-Li  assert(RegNext(!s1_valid || PopCount(s1_tag_match_way_dup_dc) <= 1.U), "tag should not match with more than 1 way")
27472dab974Scz4e  io.pseudo_tag_error_inj_done := s1_fire && wayMap((w: Int) => meta_resp(w).coh.isValid()).asUInt.orR
2751f0e2dc7SJiawei Lin
2761f0e2dc7SJiawei Lin  // when there are no tag match, we give it a Fake Meta
2771f0e2dc7SJiawei Lin  // this simplifies our logic in s2 stage
278cd2ff98bShappy-lx  val s1_hit_meta = ParallelMux(s1_tag_match_way_dup_dc.asBools, (0 until nWays).map(w => meta_resp(w)))
2791f0e2dc7SJiawei Lin  val s1_hit_coh = s1_hit_meta.coh
280cd2ff98bShappy-lx  val s1_hit_error = ParallelMux(s1_tag_match_way_dup_dc.asBools, (0 until nWays).map(w => io.extra_meta_resp(w).error))
281cd2ff98bShappy-lx  val s1_hit_prefetch = ParallelMux(s1_tag_match_way_dup_dc.asBools, (0 until nWays).map(w => io.extra_meta_resp(w).prefetch))
282cd2ff98bShappy-lx  val s1_hit_access = ParallelMux(s1_tag_match_way_dup_dc.asBools, (0 until nWays).map(w => io.extra_meta_resp(w).access))
2831f0e2dc7SJiawei Lin
284ffd3154dSCharlieLiu  // io.replace_way.set.valid := RegNext(s0_fire)
285ffd3154dSCharlieLiu  io.replace_way.set.valid := false.B
286ad3ba452Szhanglinjuan  io.replace_way.set.bits := get_idx(s1_vaddr)
28704665835SMaxpicca-Li  io.replace_way.dmWay := get_direct_map_way(s1_vaddr)
288282f71c4Shappy-lx  val s1_invalid_vec = wayMap(w => !meta_resp(w).coh.isValid())
289282f71c4Shappy-lx  val s1_have_invalid_way = s1_invalid_vec.asUInt.orR
290282f71c4Shappy-lx  val s1_invalid_way_en = ParallelPriorityMux(s1_invalid_vec.zipWithIndex.map(x => x._1 -> UIntToOH(x._2.U(nWays.W))))
291ad3ba452Szhanglinjuan
29227dc8a4dSWilliam Wang  val s1_need_replacement = !s1_tag_match_dup_dc
293ad3ba452Szhanglinjuan
294282f71c4Shappy-lx  XSPerfAccumulate("load_using_replacement", io.replace_way.set.valid && s1_need_replacement)
295282f71c4Shappy-lx
2960d32f713Shappy-lx  // query bloom filter
2970d32f713Shappy-lx  io.bloom_filter_query.query.valid := s1_valid
2980d32f713Shappy-lx  io.bloom_filter_query.query.bits.addr := io.bloom_filter_query.query.bits.get_addr(s1_paddr_dup_dcache)
2990d32f713Shappy-lx
3009ef181f4SWilliam Wang  // get s1_will_send_miss_req in lpad_s1
301a98b054bSWilliam Wang  val s1_has_permission = s1_hit_coh.onAccess(s1_req.cmd)._1
302a98b054bSWilliam Wang  val s1_new_hit_coh = s1_hit_coh.onAccess(s1_req.cmd)._3
303fb49ae6bScz4e  val s1_hit = s1_tag_match_dup_dc && s1_has_permission && s1_hit_coh === s1_new_hit_coh
304c2bbba9fSCharlieLiu  val s1_will_send_miss_req = s1_valid && !s1_nack && !s1_hit
305c2bbba9fSCharlieLiu
306c2bbba9fSCharlieLiu  // data read
307a5f58fbcSlixin  io.banked_data_read.valid := s1_fire && !s1_nack && !s1_is_prefetch
308c2bbba9fSCharlieLiu  io.banked_data_read.bits.addr := s1_vaddr
309fa5e530dScz4e  io.banked_data_read.bits.addr_dup := s1_vaddr_dup
310a5f58fbcSlixin  io.banked_data_read.bits.kill := io.lsu.s1_kill_data_read
311c2bbba9fSCharlieLiu  io.banked_data_read.bits.way_en := s1_pred_tag_match_way_dup_dc
312c2bbba9fSCharlieLiu  io.banked_data_read.bits.bankMask := s1_bank_oh
3138ffb12e4SAnzo  io.banked_data_read.bits.lqIdx := s1_req.lqIdx
314c2bbba9fSCharlieLiu  io.is128Req := s1_load128Req
315a98b054bSWilliam Wang
316026615fcSWilliam Wang  // check ecc error
3179ef181f4SWilliam Wang  val s1_flag_error = Mux(s1_need_replacement, false.B, s1_hit_error) // error reported by exist dcache error bit
3181f0e2dc7SJiawei Lin
3191f0e2dc7SJiawei Lin  // --------------------------------------------------------------------------------
3201f0e2dc7SJiawei Lin  // stage 2
3216786cfb7SWilliam Wang  // --------------------------------------------------------------------------------
3226786cfb7SWilliam Wang  // return data
3236786cfb7SWilliam Wang
3241f0e2dc7SJiawei Lin  // val s2_valid = RegEnable(next = s1_valid && !io.lsu.s1_kill, init = false.B, enable = s1_fire)
3251f0e2dc7SJiawei Lin  val s2_valid = RegInit(false.B)
32608b0bc30Shappy-lx  val s2_valid_dup = RegInit(false.B)
3271f0e2dc7SJiawei Lin  val s2_req = RegEnable(s1_req, s1_fire)
328cdbff57cSHaoyuan Feng  val s2_load128Req = RegEnable(s1_load128Req, s1_fire)
32903efd994Shappy-lx  val s2_paddr = RegEnable(s1_paddr_dup_dcache, s1_fire)
3301f0e2dc7SJiawei Lin  val s2_vaddr = RegEnable(s1_vaddr, s1_fire)
3311f0e2dc7SJiawei Lin  val s2_bank_oh = RegEnable(s1_bank_oh, s1_fire)
332c3a5fe5fShappy-lx  val s2_bank_oh_dup_0 = RegEnable(s1_bank_oh, s1_fire)
33304665835SMaxpicca-Li  val s2_wpu_pred_fail = RegEnable(s1_wpu_pred_fail, s1_fire)
33404665835SMaxpicca-Li  val s2_real_way_en = RegEnable(s1_tag_match_way_dup_dc, s1_fire)
33504665835SMaxpicca-Li  val s2_pred_way_en = RegEnable(s1_pred_tag_match_way_dup_dc, s1_fire)
33604665835SMaxpicca-Li  val s2_dm_way_num = RegEnable(s1_direct_map_way_num, s1_fire)
33704665835SMaxpicca-Li  val s2_wpu_pred_fail_and_real_hit = RegEnable(s1_wpu_pred_fail_and_real_hit, s1_fire)
33804665835SMaxpicca-Li
3391f0e2dc7SJiawei Lin  s2_ready := true.B
3401f0e2dc7SJiawei Lin
3416786cfb7SWilliam Wang  val s2_fire = s2_valid
3426786cfb7SWilliam Wang
34308b0bc30Shappy-lx  when (s1_fire) {
34408b0bc30Shappy-lx    s2_valid := !io.lsu.s1_kill
34508b0bc30Shappy-lx    s2_valid_dup := !io.lsu.s1_kill
34608b0bc30Shappy-lx  }
34708b0bc30Shappy-lx  .elsewhen(io.lsu.resp.fire) {
34808b0bc30Shappy-lx    s2_valid := false.B
34908b0bc30Shappy-lx    s2_valid_dup := false.B
35008b0bc30Shappy-lx  }
3511f0e2dc7SJiawei Lin
3521f0e2dc7SJiawei Lin  dump_pipeline_reqs("LoadPipe s2", s2_valid, s2_req)
3531f0e2dc7SJiawei Lin
354dcd58560SWilliam Wang
3551f0e2dc7SJiawei Lin  // hit, miss, nack, permission checking
35603efd994Shappy-lx  // dcache side tag match
35772dab974Scz4e  val s2_tag_errors = RegEnable(s1_tag_errors, s1_fire)
35827dc8a4dSWilliam Wang  val s2_tag_match_way = RegEnable(s1_tag_match_way_dup_dc, s1_fire)
35927dc8a4dSWilliam Wang  val s2_tag_match = RegEnable(s1_tag_match_dup_dc, s1_fire)
3601f0e2dc7SJiawei Lin
36108b0bc30Shappy-lx  val s2_can_send_miss_req = RegEnable(s1_will_send_miss_req, s1_fire)
36208b0bc30Shappy-lx  val s2_can_send_miss_req_dup = RegEnable(s1_will_send_miss_req, s1_fire)
36308b0bc30Shappy-lx
36408b0bc30Shappy-lx  val s2_miss_req_valid     = s2_valid && s2_can_send_miss_req
36508b0bc30Shappy-lx  val s2_miss_req_valid_dup = s2_valid_dup && s2_can_send_miss_req_dup
36608b0bc30Shappy-lx  val s2_miss_req_fire      = s2_miss_req_valid_dup && io.miss_req.ready
36708b0bc30Shappy-lx
36803efd994Shappy-lx  // lsu side tag match
36927dc8a4dSWilliam Wang  val s2_hit_dup_lsu = RegNext(s1_tag_match_dup_lsu)
37003efd994Shappy-lx
371144422dcSMaxpicca-Li  io.lsu.s2_hit := s2_hit_dup_lsu && !s2_wpu_pred_fail
37203efd994Shappy-lx
3731f0e2dc7SJiawei Lin  val s2_hit_meta = RegEnable(s1_hit_meta, s1_fire)
3741f0e2dc7SJiawei Lin  val s2_hit_coh = RegEnable(s1_hit_coh, s1_fire)
375dcd58560SWilliam Wang  val s2_has_permission = s2_hit_coh.onAccess(s2_req.cmd)._1 // for write prefetch
376dcd58560SWilliam Wang  val s2_new_hit_coh = s2_hit_coh.onAccess(s2_req.cmd)._3 // for write prefetch
3771f0e2dc7SJiawei Lin
3781f0e2dc7SJiawei Lin  // when req got nacked, upper levels should replay this request
3791f0e2dc7SJiawei Lin  // nacked or not
3801f0e2dc7SJiawei Lin  val s2_nack_hit = RegEnable(s1_nack, s1_fire)
3811f0e2dc7SJiawei Lin  // can no allocate mshr for load miss
38208b0bc30Shappy-lx  val s2_nack_no_mshr = s2_miss_req_valid_dup && !io.miss_req.ready
38308b0bc30Shappy-lx  // block with a wbq valid req
38408b0bc30Shappy-lx  val s2_nack_wbq_conflict = s2_miss_req_valid_dup && io.wbq_block_miss_req
3851f0e2dc7SJiawei Lin  // Bank conflict on data arrays
3861f0e2dc7SJiawei Lin  val s2_nack_data = RegEnable(!io.banked_data_read.ready, s1_fire)
38708b0bc30Shappy-lx  val s2_nack = s2_nack_hit || s2_nack_no_mshr || s2_nack_data || s2_nack_wbq_conflict
388fa9ac9b6SWilliam Wang  // s2 miss merged
389*51f9a957Scz4e  val s2_miss_merged = s2_miss_req_fire && !io.miss_req.bits.cancel && !io.wbq_block_miss_req && io.miss_resp.merged
3901f0e2dc7SJiawei Lin
39103efd994Shappy-lx  val s2_bank_addr = addr_to_dcache_bank(s2_paddr)
3921f0e2dc7SJiawei Lin  dontTouch(s2_bank_addr)
3931f0e2dc7SJiawei Lin
3949ef181f4SWilliam Wang  val s2_instrtype = s2_req.instrtype
3959ef181f4SWilliam Wang
39631d5a9c4Ssfencevma  val s2_tag_error = WireInit(false.B)
3979ef181f4SWilliam Wang  val s2_flag_error = RegEnable(s1_flag_error, s1_fire)
398026615fcSWilliam Wang
3993af6aa6eSWilliam Wang  val s2_hit_prefetch = RegEnable(s1_hit_prefetch, s1_fire)
4003af6aa6eSWilliam Wang  val s2_hit_access = RegEnable(s1_hit_access, s1_fire)
4013af6aa6eSWilliam Wang
402144422dcSMaxpicca-Li  val s2_hit = s2_tag_match && s2_has_permission && s2_hit_coh === s2_new_hit_coh && !s2_wpu_pred_fail
4033f4ec46fSCODE-JTZ
404d4564868Sweiding liu  val s2_data128bit = Cat(io.banked_data_resp(1).raw_data, io.banked_data_resp(0).raw_data)
40508b0bc30Shappy-lx  val s2_resp_data  = s2_data128bit
406d4564868Sweiding liu
4071f0e2dc7SJiawei Lin  // only dump these signals when they are actually valid
4081f0e2dc7SJiawei Lin  dump_pipeline_valids("LoadPipe s2", "s2_hit", s2_valid && s2_hit)
4091f0e2dc7SJiawei Lin  dump_pipeline_valids("LoadPipe s2", "s2_nack", s2_valid && s2_nack)
4101f0e2dc7SJiawei Lin  dump_pipeline_valids("LoadPipe s2", "s2_nack_hit", s2_valid && s2_nack_hit)
4111f0e2dc7SJiawei Lin  dump_pipeline_valids("LoadPipe s2", "s2_nack_no_mshr", s2_valid && s2_nack_no_mshr)
4121f0e2dc7SJiawei Lin
41331d5a9c4Ssfencevma  if(EnableTagEcc) {
41472dab974Scz4e    s2_tag_error := s2_tag_errors.orR // error reported by tag ecc check
41531d5a9c4Ssfencevma  }
41672dab974Scz4e  io.pseudo_data_error_inj_done := s2_fire && s2_hit && !io.bank_conflict_slow
41772dab974Scz4e  io.pseudo_error.ready := false.B
41831d5a9c4Ssfencevma
4191f0e2dc7SJiawei Lin  // send load miss to miss queue
42008b0bc30Shappy-lx  io.miss_req.valid := s2_miss_req_valid
4211f0e2dc7SJiawei Lin  io.miss_req.bits := DontCare
4223f4ec46fSCODE-JTZ  io.miss_req.bits.source := s2_instrtype
4235adc4829SYanqin Li  io.miss_req.bits.pf_source := RegNext(RegNext(io.lsu.pf_source))  // TODO: clock gate
4241f0e2dc7SJiawei Lin  io.miss_req.bits.cmd := s2_req.cmd
42503efd994Shappy-lx  io.miss_req.bits.addr := get_block_addr(s2_paddr)
4261f0e2dc7SJiawei Lin  io.miss_req.bits.vaddr := s2_vaddr
427ad3ba452Szhanglinjuan  io.miss_req.bits.req_coh := s2_hit_coh
428a469aa4bSWilliam Wang  io.miss_req.bits.cancel := io.lsu.s2_kill || s2_tag_error
4292db9ec44SLinJiawei  io.miss_req.bits.pc := io.lsu.s2_pc
430d2945707SHuijin Li  io.miss_req.bits.lqIdx := io.lsu.req.bits.lqIdx
43108b0bc30Shappy-lx
43208b0bc30Shappy-lx  //send load miss to wbq
43308b0bc30Shappy-lx  io.wbq_conflict_check.valid := s2_miss_req_valid_dup
43408b0bc30Shappy-lx  io.wbq_conflict_check.bits := get_block_addr(s2_paddr)
43508b0bc30Shappy-lx
4361f0e2dc7SJiawei Lin  // send back response
437144422dcSMaxpicca-Li  val resp = Wire(ValidIO(new DCacheWordResp))
4381f0e2dc7SJiawei Lin  resp.valid := s2_valid
4391f0e2dc7SJiawei Lin  resp.bits := DontCare
440144422dcSMaxpicca-Li  // resp.bits.data := s2_word_decoded
441144422dcSMaxpicca-Li  // resp.bits.data := banked_data_resp_word.raw_data
4421f0e2dc7SJiawei Lin  // * on miss or nack, upper level should replay request
4431f0e2dc7SJiawei Lin  // but if we successfully sent the request to miss queue
4441f0e2dc7SJiawei Lin  // upper level does not need to replay request
4451f0e2dc7SJiawei Lin  // they can sit in load queue and wait for refill
4461f0e2dc7SJiawei Lin  //
4471f0e2dc7SJiawei Lin  // * report a miss if bank conflict is detected
44804665835SMaxpicca-Li  val real_miss = !s2_real_way_en.orR
4490d32f713Shappy-lx
4500d32f713Shappy-lx  resp.bits.real_miss := real_miss
45114a67055Ssfencevma  resp.bits.miss := real_miss
45208b0bc30Shappy-lx  resp.bits.data := s2_resp_data
453da3bf434SMaxpicca-Li  io.lsu.s2_first_hit := s2_req.isFirstIssue && s2_hit
454144422dcSMaxpicca-Li  // load pipe need replay when there is a bank conflict or wpu predict fail
455*51f9a957Scz4e  resp.bits.replay := (resp.bits.miss && (s2_nack || io.miss_req.bits.cancel)) || io.bank_conflict_slow || s2_wpu_pred_fail
456*51f9a957Scz4e  resp.bits.replayCarry.valid := (resp.bits.miss && (s2_nack || io.miss_req.bits.cancel)) || io.bank_conflict_slow || s2_wpu_pred_fail
457144422dcSMaxpicca-Li  resp.bits.replayCarry.real_way_en := s2_real_way_en
4583af6aa6eSWilliam Wang  resp.bits.meta_prefetch := s2_hit_prefetch
4593af6aa6eSWilliam Wang  resp.bits.meta_access := s2_hit_access
46092bcee1cScz4e  resp.bits.tag_error := false.B
461683c1411Shappy-lx  resp.bits.mshr_id := io.miss_resp.id
462*51f9a957Scz4e  resp.bits.handled := s2_miss_req_fire && !io.miss_req.bits.cancel && !io.wbq_block_miss_req && io.miss_resp.handled
463da3bf434SMaxpicca-Li  resp.bits.debug_robIdx := s2_req.debug_robIdx
46404665835SMaxpicca-Li  // debug info
46504665835SMaxpicca-Li  io.lsu.s2_first_hit := s2_req.isFirstIssue && s2_hit
46604665835SMaxpicca-Li  io.lsu.debug_s2_real_way_num := OneHot.OHToUIntStartOne(s2_real_way_en)
46704665835SMaxpicca-Li  if(dwpuParam.enWPU) {
46804665835SMaxpicca-Li    io.lsu.debug_s2_pred_way_num := OneHot.OHToUIntStartOne(s2_pred_way_en)
46904665835SMaxpicca-Li  }else{
47004665835SMaxpicca-Li    io.lsu.debug_s2_pred_way_num := 0.U
47104665835SMaxpicca-Li  }
47204665835SMaxpicca-Li  if(dwpuParam.enWPU && dwpuParam.enCfPred || !env.FPGAPlatform){
47304665835SMaxpicca-Li    io.lsu.debug_s2_dm_way_num :=  s2_dm_way_num + 1.U
47404665835SMaxpicca-Li  }else{
47504665835SMaxpicca-Li    io.lsu.debug_s2_dm_way_num := 0.U
47604665835SMaxpicca-Li  }
477a469aa4bSWilliam Wang
47804665835SMaxpicca-Li
4793af6aa6eSWilliam Wang  XSPerfAccumulate("dcache_read_bank_conflict", io.bank_conflict_slow && s2_valid)
4806070f1e9Shappy-lx  XSPerfAccumulate("dcache_read_from_prefetched_line", s2_valid && isPrefetchRelated(s2_hit_prefetch) && !resp.bits.miss)
4816070f1e9Shappy-lx  XSPerfAccumulate("dcache_first_read_from_prefetched_line", s2_valid && isPrefetchRelated(s2_hit_prefetch) && !resp.bits.miss && !s2_hit_access)
4820d32f713Shappy-lx
4830d32f713Shappy-lx  // if ldu0 and ldu1 hit the same, count for 1
4840d32f713Shappy-lx  val total_prefetch = s2_valid && (s2_req.instrtype === DCACHE_PREFETCH_SOURCE.U)
4850d32f713Shappy-lx  val late_hit_prefetch = s2_valid && s2_hit && (s2_req.instrtype === DCACHE_PREFETCH_SOURCE.U)
4860d32f713Shappy-lx  val late_load_hit = s2_valid && s2_hit && (s2_req.instrtype === DCACHE_PREFETCH_SOURCE.U) && !isFromL1Prefetch(s2_hit_prefetch)
4870d32f713Shappy-lx  val late_prefetch_hit = s2_valid && s2_hit && (s2_req.instrtype === DCACHE_PREFETCH_SOURCE.U) && isFromL1Prefetch(s2_hit_prefetch)
48808b0bc30Shappy-lx  val useless_prefetch = s2_miss_req_fire && (s2_req.instrtype === DCACHE_PREFETCH_SOURCE.U)
4890d32f713Shappy-lx  val useful_prefetch = s2_valid && (s2_req.instrtype === DCACHE_PREFETCH_SOURCE.U) && resp.bits.handled && !io.miss_resp.merged
4900d32f713Shappy-lx
4910d32f713Shappy-lx  val prefetch_hit = s2_valid && (s2_req.instrtype =/= DCACHE_PREFETCH_SOURCE.U) && s2_hit && isFromL1Prefetch(s2_hit_prefetch) && s2_req.isFirstIssue
4920d32f713Shappy-lx
4930d32f713Shappy-lx  io.prefetch_info.naive.total_prefetch := total_prefetch
4940d32f713Shappy-lx  io.prefetch_info.naive.late_hit_prefetch := late_hit_prefetch
4950d32f713Shappy-lx  io.prefetch_info.naive.late_load_hit := late_load_hit
4960d32f713Shappy-lx  io.prefetch_info.naive.late_prefetch_hit := late_prefetch_hit
4970d32f713Shappy-lx  io.prefetch_info.naive.useless_prefetch := useless_prefetch
4980d32f713Shappy-lx  io.prefetch_info.naive.useful_prefetch := useful_prefetch
4990d32f713Shappy-lx  io.prefetch_info.naive.prefetch_hit := prefetch_hit
5000d32f713Shappy-lx
5010d32f713Shappy-lx  io.prefetch_info.fdp.demand_miss := s2_valid && (s2_req.instrtype =/= DCACHE_PREFETCH_SOURCE.U) && !s2_hit && s2_req.isFirstIssue
5020d32f713Shappy-lx  io.prefetch_info.fdp.pollution := io.prefetch_info.fdp.demand_miss && io.bloom_filter_query.resp.valid && io.bloom_filter_query.resp.bits.res
5033f4ec46fSCODE-JTZ
5041f0e2dc7SJiawei Lin  io.lsu.resp.valid := resp.valid
5051f0e2dc7SJiawei Lin  io.lsu.resp.bits := resp.bits
5061f0e2dc7SJiawei Lin  assert(RegNext(!(resp.valid && !io.lsu.resp.ready)), "lsu should be ready in s2")
5071f0e2dc7SJiawei Lin
5088b33cd30Sklin02  resp.bits.dump(resp.valid)
5091f0e2dc7SJiawei Lin
51027dc8a4dSWilliam Wang  io.lsu.debug_s1_hit_way := s1_tag_match_way_dup_dc
5111f0e2dc7SJiawei Lin  io.lsu.s1_disable_fast_wakeup := io.disable_ld_fast_wakeup
512594c5198Ssfencevma  io.lsu.s2_bank_conflict := io.bank_conflict_slow
51304665835SMaxpicca-Li  io.lsu.s2_wpu_pred_fail := s2_wpu_pred_fail_and_real_hit
514*51f9a957Scz4e  io.lsu.s2_mq_nack       := (resp.bits.miss && (s2_nack_no_mshr || io.miss_req.bits.cancel || io.wbq_block_miss_req))
5151f0e2dc7SJiawei Lin  assert(RegNext(s1_ready && s2_ready), "load pipeline should never be blocked")
5161f0e2dc7SJiawei Lin
5176786cfb7SWilliam Wang  // --------------------------------------------------------------------------------
5186786cfb7SWilliam Wang  // stage 3
5196786cfb7SWilliam Wang  // --------------------------------------------------------------------------------
520144422dcSMaxpicca-Li  // report ecc error and get selected dcache data
5216786cfb7SWilliam Wang
5226786cfb7SWilliam Wang  val s3_valid = RegNext(s2_valid)
523cdbff57cSHaoyuan Feng  val s3_load128Req = RegEnable(s2_load128Req, s2_fire)
5243af6aa6eSWilliam Wang  val s3_vaddr = RegEnable(s2_vaddr, s2_fire)
52503efd994Shappy-lx  val s3_paddr = RegEnable(s2_paddr, s2_fire)
5266786cfb7SWilliam Wang  val s3_hit = RegEnable(s2_hit, s2_fire)
5273af6aa6eSWilliam Wang  val s3_tag_match_way = RegEnable(s2_tag_match_way, s2_fire)
5280d32f713Shappy-lx  val s3_req_instrtype = RegEnable(s2_req.instrtype, s2_fire)
5290d32f713Shappy-lx  val s3_is_prefetch = s3_req_instrtype === DCACHE_PREFETCH_SOURCE.U
5306786cfb7SWilliam Wang
53108b0bc30Shappy-lx  val s3_banked_data_resp_word = RegEnable(s2_resp_data, s2_fire)
532cdbff57cSHaoyuan Feng  val s3_data_error = Mux(s3_load128Req, io.read_error_delayed.asUInt.orR, io.read_error_delayed(0)) && s3_hit
5336786cfb7SWilliam Wang  val s3_tag_error = RegEnable(s2_tag_error, s2_fire)
5346786cfb7SWilliam Wang  val s3_flag_error = RegEnable(s2_flag_error, s2_fire)
5350d32f713Shappy-lx  val s3_hit_prefetch = RegEnable(s2_hit_prefetch, s2_fire)
5366786cfb7SWilliam Wang  val s3_error = s3_tag_error || s3_flag_error || s3_data_error
5376786cfb7SWilliam Wang
5386786cfb7SWilliam Wang  // error_delayed signal will be used to update uop.exception 1 cycle after load writeback
53903efd994Shappy-lx  resp.bits.error_delayed := s3_error && (s3_hit || s3_tag_error) && s3_valid
540144422dcSMaxpicca-Li  resp.bits.data_delayed := s3_banked_data_resp_word
541b9e121dfShappy-lx  resp.bits.replacementUpdated := io.replace_access.valid
5426786cfb7SWilliam Wang
5436786cfb7SWilliam Wang  // report tag / data / l2 error (with paddr) to bus error unit
5440184a80eSYanqin Li  io.error := 0.U.asTypeOf(ValidIO(new L1CacheErrorInfo))
5450184a80eSYanqin Li  io.error.bits.report_to_beu := (s3_tag_error || s3_data_error) && s3_valid
5460184a80eSYanqin Li  io.error.bits.paddr := s3_paddr
5470184a80eSYanqin Li  io.error.bits.source.tag := s3_tag_error
5480184a80eSYanqin Li  io.error.bits.source.data := s3_data_error
5490184a80eSYanqin Li  io.error.bits.source.l2 := s3_flag_error
5500184a80eSYanqin Li  io.error.bits.opType.load := true.B
5516786cfb7SWilliam Wang  // report tag error / l2 corrupted to CACHE_ERROR csr
5526786cfb7SWilliam Wang  io.error.valid := s3_error && s3_valid
5536786cfb7SWilliam Wang
554ffd3154dSCharlieLiu  io.replace_access.valid := s3_valid && s3_hit
555d2b20d1aSTang Haojin  io.replace_access.bits.set := RegNext(RegNext(get_idx(s1_req.vaddr)))
556ffd3154dSCharlieLiu  io.replace_access.bits.way := RegNext(RegNext(OHToUInt(s1_tag_match_way_dup_dc)))
55792816bbcSWilliam Wang
5583af6aa6eSWilliam Wang  // update access bit
5590d32f713Shappy-lx  io.access_flag_write.valid := s3_valid && s3_hit && !s3_is_prefetch
5603af6aa6eSWilliam Wang  io.access_flag_write.bits.idx := get_idx(s3_vaddr)
5613af6aa6eSWilliam Wang  io.access_flag_write.bits.way_en := s3_tag_match_way
5623af6aa6eSWilliam Wang  io.access_flag_write.bits.flag := true.B
5633af6aa6eSWilliam Wang
5640d32f713Shappy-lx  // clear prefetch source when prefetch hit
5650d32f713Shappy-lx  val s3_clear_pf_flag_en = s3_valid && s3_hit && !s3_is_prefetch && isFromL1Prefetch(s3_hit_prefetch)
5660d32f713Shappy-lx  io.prefetch_flag_write.valid := s3_clear_pf_flag_en && !io.counter_filter_query.resp
5670d32f713Shappy-lx  io.prefetch_flag_write.bits.idx := get_idx(s3_vaddr)
5680d32f713Shappy-lx  io.prefetch_flag_write.bits.way_en := s3_tag_match_way
5696070f1e9Shappy-lx  io.prefetch_flag_write.bits.source := L1_HW_PREFETCH_CLEAR
5700d32f713Shappy-lx
5710d32f713Shappy-lx  io.counter_filter_query.req.valid := s3_clear_pf_flag_en
5720d32f713Shappy-lx  io.counter_filter_query.req.bits.idx := get_idx(s3_vaddr)
5730d32f713Shappy-lx  io.counter_filter_query.req.bits.way := OHToUInt(s3_tag_match_way)
5740d32f713Shappy-lx
5750d32f713Shappy-lx  io.counter_filter_enq.valid := io.prefetch_flag_write.valid
5760d32f713Shappy-lx  io.counter_filter_enq.bits.idx := get_idx(s3_vaddr)
5770d32f713Shappy-lx  io.counter_filter_enq.bits.way := OHToUInt(s3_tag_match_way)
5780d32f713Shappy-lx
5790d32f713Shappy-lx  io.prefetch_info.fdp.useful_prefetch := s3_clear_pf_flag_en && !io.counter_filter_query.resp
5800d32f713Shappy-lx
5810d32f713Shappy-lx  XSPerfAccumulate("s3_pf_hit", s3_clear_pf_flag_en)
5820d32f713Shappy-lx  XSPerfAccumulate("s3_pf_hit_filter", s3_clear_pf_flag_en && !io.counter_filter_query.resp)
5830d32f713Shappy-lx
5846786cfb7SWilliam Wang  // --------------------------------------------------------------------------------
5851f0e2dc7SJiawei Lin  // Debug logging functions
5861f0e2dc7SJiawei Lin  def dump_pipeline_reqs(pipeline_stage_name: String, valid: Bool,
5871f0e2dc7SJiawei Lin    req: DCacheWordReq ) = {
5888b33cd30Sklin02      XSDebug(valid, s"$pipeline_stage_name: ")
5898b33cd30Sklin02      req.dump(valid)
5901f0e2dc7SJiawei Lin  }
5911f0e2dc7SJiawei Lin
5921f0e2dc7SJiawei Lin  def dump_pipeline_valids(pipeline_stage_name: String, signal_name: String, valid: Bool) = {
5938b33cd30Sklin02    XSDebug(valid, s"$pipeline_stage_name $signal_name\n")
5941f0e2dc7SJiawei Lin  }
5951f0e2dc7SJiawei Lin
5960d32f713Shappy-lx  val load_trace = Wire(new LoadPfDbBundle)
5970d32f713Shappy-lx  val pf_trace = Wire(new LoadPfDbBundle)
5980d32f713Shappy-lx  val miss_trace = Wire(new LoadPfDbBundle)
5990d32f713Shappy-lx  val mshr_trace = Wire(new LoadPfDbBundle)
6000d32f713Shappy-lx
6010d32f713Shappy-lx  load_trace.paddr := get_block_addr(s2_paddr)
6020d32f713Shappy-lx  pf_trace.paddr := get_block_addr(s2_paddr)
6030d32f713Shappy-lx  miss_trace.paddr := get_block_addr(s2_paddr)
6040d32f713Shappy-lx  mshr_trace.paddr := get_block_addr(s2_paddr)
6050d32f713Shappy-lx
6060d32f713Shappy-lx  val table_load = ChiselDB.createTable("LoadTrace" + id.toString + "_hart"+ p(XSCoreParamsKey).HartId.toString, new LoadPfDbBundle, basicDB = false)
6070d32f713Shappy-lx  val site_load = "LoadPipe_load" + id.toString
6080d32f713Shappy-lx  table_load.log(load_trace, s2_valid && s2_req.isFirstIssue && (s2_req.instrtype =/= DCACHE_PREFETCH_SOURCE.U), site_load, clock, reset)
6090d32f713Shappy-lx
6100d32f713Shappy-lx  val table_pf = ChiselDB.createTable("LoadPfTrace" + id.toString + "_hart"+ p(XSCoreParamsKey).HartId.toString, new LoadPfDbBundle, basicDB = false)
6110d32f713Shappy-lx  val site_pf = "LoadPipe_pf" + id.toString
6120d32f713Shappy-lx  table_pf.log(pf_trace, s2_valid && (s2_req.instrtype === DCACHE_PREFETCH_SOURCE.U), site_pf, clock, reset)
6130d32f713Shappy-lx
6140d32f713Shappy-lx  val table_miss = ChiselDB.createTable("LoadTraceMiss" + id.toString + "_hart"+ p(XSCoreParamsKey).HartId.toString, new LoadPfDbBundle, basicDB = false)
6150d32f713Shappy-lx  val site_load_miss = "LoadPipe_load_miss" + id.toString
6160d32f713Shappy-lx  table_miss.log(miss_trace, s2_valid && s2_req.isFirstIssue && (s2_req.instrtype =/= DCACHE_PREFETCH_SOURCE.U) && real_miss, site_load_miss, clock, reset)
6170d32f713Shappy-lx
6180d32f713Shappy-lx  val table_mshr = ChiselDB.createTable("LoadPfMshr" + id.toString + "_hart"+ p(XSCoreParamsKey).HartId.toString, new LoadPfDbBundle, basicDB = false)
6190d32f713Shappy-lx  val site_mshr = "LoadPipe_mshr" + id.toString
620935edac4STang Haojin  table_mshr.log(mshr_trace, s2_valid && (s2_req.instrtype === DCACHE_PREFETCH_SOURCE.U) && io.miss_req.fire, site_mshr, clock, reset)
6210d32f713Shappy-lx
6221f0e2dc7SJiawei Lin  // performance counters
623935edac4STang Haojin  XSPerfAccumulate("load_req", io.lsu.req.fire)
6241f0e2dc7SJiawei Lin  XSPerfAccumulate("load_s1_kill", s1_fire && io.lsu.s1_kill)
62527dc8a4dSWilliam Wang  XSPerfAccumulate("load_hit_way", s1_fire && s1_tag_match_dup_dc)
626935edac4STang Haojin  XSPerfAccumulate("load_replay", io.lsu.resp.fire && resp.bits.replay)
627935edac4STang Haojin  XSPerfAccumulate("load_replay_for_dcache_data_nack", io.lsu.resp.fire && resp.bits.replay && s2_nack_data)
628935edac4STang Haojin  XSPerfAccumulate("load_replay_for_dcache_no_mshr", io.lsu.resp.fire && resp.bits.replay && s2_nack_no_mshr)
629935edac4STang Haojin  XSPerfAccumulate("load_replay_for_dcache_conflict", io.lsu.resp.fire && resp.bits.replay && io.bank_conflict_slow)
630935edac4STang Haojin  XSPerfAccumulate("load_replay_for_dcache_wpu_pred_fail", io.lsu.resp.fire && resp.bits.replay && s2_wpu_pred_fail)
631935edac4STang Haojin  XSPerfAccumulate("load_hit", io.lsu.resp.fire && !real_miss)
632935edac4STang Haojin  XSPerfAccumulate("load_miss", io.lsu.resp.fire && real_miss)
633935edac4STang Haojin  XSPerfAccumulate("load_succeed", io.lsu.resp.fire && !resp.bits.miss && !resp.bits.replay)
634935edac4STang Haojin  XSPerfAccumulate("load_miss_or_conflict", io.lsu.resp.fire && resp.bits.miss)
63527dc8a4dSWilliam Wang  XSPerfAccumulate("actual_ld_fast_wakeup", s1_fire && s1_tag_match_dup_dc && !io.disable_ld_fast_wakeup)
636935edac4STang Haojin  XSPerfAccumulate("ideal_ld_fast_wakeup", io.banked_data_read.fire && s1_tag_match_dup_dc)
637cd365d4cSrvcoresjw
638cd365d4cSrvcoresjw  val perfEvents = Seq(
639935edac4STang Haojin    ("load_req                 ", io.lsu.req.fire                                               ),
640935edac4STang Haojin    ("load_replay              ", io.lsu.resp.fire && resp.bits.replay                          ),
641935edac4STang Haojin    ("load_replay_for_data_nack", io.lsu.resp.fire && resp.bits.replay && s2_nack_data          ),
642935edac4STang Haojin    ("load_replay_for_no_mshr  ", io.lsu.resp.fire && resp.bits.replay && s2_nack_no_mshr       ),
643935edac4STang Haojin    ("load_replay_for_conflict ", io.lsu.resp.fire && resp.bits.replay && io.bank_conflict_slow ),
644cd365d4cSrvcoresjw  )
6451ca0e4f3SYinan Xu  generatePerfEvent()
6461f0e2dc7SJiawei Lin}
647