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. 15c49ebec8SHaoyuan Feng* 16c49ebec8SHaoyuan Feng* 17c49ebec8SHaoyuan Feng* Acknowledgement 18c49ebec8SHaoyuan Feng* 19c49ebec8SHaoyuan Feng* This implementation is inspired by several key papers: 20c49ebec8SHaoyuan Feng* [1] David Kroft. "[Lockup-free instruction fetch/prefetch cache organization.] 21c49ebec8SHaoyuan Feng* (https://dl.acm.org/doi/10.5555/800052.801868)" 8th Annual Symposium on Computer Architecture (ISCA). 1981. 221f0e2dc7SJiawei Lin***************************************************************************************/ 231f0e2dc7SJiawei Lin 241f0e2dc7SJiawei Linpackage xiangshan.cache 251f0e2dc7SJiawei Lin 261f0e2dc7SJiawei Linimport chisel3._ 271f0e2dc7SJiawei Linimport chisel3.util._ 2838c29594Szhanglinjuanimport chisel3.experimental.dataview._ 297f37d55fSTang Haojinimport coupledL2.VaddrKey 30d2945707SHuijin Liimport coupledL2.IsKeywordKey 317f37d55fSTang Haojinimport difftest._ 32ad3ba452Szhanglinjuanimport freechips.rocketchip.tilelink.ClientStates._ 33ad3ba452Szhanglinjuanimport freechips.rocketchip.tilelink.MemoryOpCategories._ 34ad3ba452Szhanglinjuanimport freechips.rocketchip.tilelink.TLPermissions._ 35dc4fac13SCharlieLiuimport freechips.rocketchip.tilelink.TLMessages._ 367f37d55fSTang Haojinimport freechips.rocketchip.tilelink._ 377f37d55fSTang Haojinimport huancun.{AliasKey, DirtyKey, PrefetchKey} 387f37d55fSTang Haojinimport org.chipsalliance.cde.config.Parameters 397f37d55fSTang Haojinimport utility._ 407f37d55fSTang Haojinimport utils._ 417f37d55fSTang Haojinimport xiangshan._ 427f37d55fSTang Haojinimport xiangshan.mem.AddPipelineReg 430d32f713Shappy-lximport xiangshan.mem.prefetch._ 447f37d55fSTang Haojinimport xiangshan.mem.trace._ 45d2945707SHuijin Liimport xiangshan.mem.LqPtr 461f0e2dc7SJiawei Lin 47c731e79fSWilliam Wangclass MissReqWoStoreData(implicit p: Parameters) extends DCacheBundle { 481f0e2dc7SJiawei Lin val source = UInt(sourceTypeWidth.W) 490d32f713Shappy-lx val pf_source = UInt(L1PfSourceBits.W) 501f0e2dc7SJiawei Lin val cmd = UInt(M_SZ.W) 511f0e2dc7SJiawei Lin val addr = UInt(PAddrBits.W) 521f0e2dc7SJiawei Lin val vaddr = UInt(VAddrBits.W) 532db9ec44SLinJiawei val pc = UInt(VAddrBits.W) 541f0e2dc7SJiawei Lin 55d2945707SHuijin Li val lqIdx = new LqPtr 561f0e2dc7SJiawei Lin // store 57c731e79fSWilliam Wang val full_overwrite = Bool() 581f0e2dc7SJiawei Lin 5938c29594Szhanglinjuan // amo 601f0e2dc7SJiawei Lin val word_idx = UInt(log2Up(blockWords).W) 6138c29594Szhanglinjuan val amo_data = UInt(QuadWordBits.W) 6238c29594Szhanglinjuan val amo_mask = UInt(QuadWordBytes.W) 6338c29594Szhanglinjuan val amo_cmp = UInt(QuadWordBits.W) // data to be compared in AMOCAS 641f0e2dc7SJiawei Lin 65ad3ba452Szhanglinjuan val req_coh = new ClientMetadata 661f0e2dc7SJiawei Lin val id = UInt(reqIdWidth.W) 671f0e2dc7SJiawei Lin 68a98b054bSWilliam Wang // For now, miss queue entry req is actually valid when req.valid && !cancel 69a98b054bSWilliam Wang // * req.valid is fast to generate 70a98b054bSWilliam Wang // * cancel is slow to generate, it will not be used until the last moment 71a98b054bSWilliam Wang // 72a98b054bSWilliam Wang // cancel may come from the following sources: 73a98b054bSWilliam Wang // 1. miss req blocked by writeback queue: 74a98b054bSWilliam Wang // a writeback req of the same address is in progress 75a98b054bSWilliam Wang // 2. pmp check failed 76a98b054bSWilliam Wang val cancel = Bool() // cancel is slow to generate, it will cancel missreq.valid 77a98b054bSWilliam Wang 7800575ac8SWilliam Wang // Req source decode 7900575ac8SWilliam Wang // Note that req source is NOT cmd type 8000575ac8SWilliam Wang // For instance, a req which isFromPrefetch may have R or W cmd 8100575ac8SWilliam Wang def isFromLoad = source === LOAD_SOURCE.U 8200575ac8SWilliam Wang def isFromStore = source === STORE_SOURCE.U 8300575ac8SWilliam Wang def isFromAMO = source === AMO_SOURCE.U 8400575ac8SWilliam Wang def isFromPrefetch = source >= DCACHE_PREFETCH_SOURCE.U 850d32f713Shappy-lx def isPrefetchWrite = source === DCACHE_PREFETCH_SOURCE.U && cmd === MemoryOpConstants.M_PFW 860d32f713Shappy-lx def isPrefetchRead = source === DCACHE_PREFETCH_SOURCE.U && cmd === MemoryOpConstants.M_PFR 87ad3ba452Szhanglinjuan def hit = req_coh.isValid() 881f0e2dc7SJiawei Lin} 891f0e2dc7SJiawei Lin 90c731e79fSWilliam Wangclass MissReqStoreData(implicit p: Parameters) extends DCacheBundle { 91c731e79fSWilliam Wang // store data and store mask will be written to miss queue entry 92c731e79fSWilliam Wang // 1 cycle after req.fire() and meta write 93c731e79fSWilliam Wang val store_data = UInt((cfg.blockBytes * 8).W) 94c731e79fSWilliam Wang val store_mask = UInt(cfg.blockBytes.W) 95c731e79fSWilliam Wang} 96c731e79fSWilliam Wang 97ffd3154dSCharlieLiuclass MissQueueRefillInfo(implicit p: Parameters) extends MissReqStoreData { 98ffd3154dSCharlieLiu // refill_info for mainpipe req awake 99ffd3154dSCharlieLiu val miss_param = UInt(TLPermissions.bdWidth.W) 100ffd3154dSCharlieLiu val miss_dirty = Bool() 1011b0de924SCharlieLiu val error = Bool() 102ffd3154dSCharlieLiu} 103ffd3154dSCharlieLiu 104c731e79fSWilliam Wangclass MissReq(implicit p: Parameters) extends MissReqWoStoreData { 105c731e79fSWilliam Wang // store data and store mask will be written to miss queue entry 106c731e79fSWilliam Wang // 1 cycle after req.fire() and meta write 107c731e79fSWilliam Wang val store_data = UInt((cfg.blockBytes * 8).W) 108c731e79fSWilliam Wang val store_mask = UInt(cfg.blockBytes.W) 109c731e79fSWilliam Wang 110c731e79fSWilliam Wang def toMissReqStoreData(): MissReqStoreData = { 111c731e79fSWilliam Wang val out = Wire(new MissReqStoreData) 112c731e79fSWilliam Wang out.store_data := store_data 113c731e79fSWilliam Wang out.store_mask := store_mask 114c731e79fSWilliam Wang out 115c731e79fSWilliam Wang } 116e771db6cSWilliam Wang 117e771db6cSWilliam Wang def toMissReqWoStoreData(): MissReqWoStoreData = { 11838c29594Szhanglinjuan this.viewAsSupertype(new MissReqWoStoreData) 119e771db6cSWilliam Wang } 120c731e79fSWilliam Wang} 121c731e79fSWilliam Wang 122683c1411Shappy-lxclass MissResp(implicit p: Parameters) extends DCacheBundle { 123683c1411Shappy-lx val id = UInt(log2Up(cfg.nMissEntries).W) 124b9e121dfShappy-lx // cache miss request is handled by miss queue, either merged or newly allocated 125b9e121dfShappy-lx val handled = Bool() 126fa9ac9b6SWilliam Wang // cache req missed, merged into one of miss queue entries 127fa9ac9b6SWilliam Wang // i.e. !miss_merged means this access is the first miss for this cacheline 128fa9ac9b6SWilliam Wang val merged = Bool() 129683c1411Shappy-lx} 130683c1411Shappy-lx 1316b5c3d02Shappy-lx 1326b5c3d02Shappy-lx/** 1336b5c3d02Shappy-lx * miss queue enq logic: enq is now splited into 2 cycles 1346b5c3d02Shappy-lx * +---------------------------------------------------------------------+ pipeline reg +-------------------------+ 1356b5c3d02Shappy-lx * + s0: enq source arbiter, judge mshr alloc or merge + +-------+ + s1: real alloc or merge + 1366b5c3d02Shappy-lx * + +-----+ primary_fire? -> + | alloc | + + 1376b5c3d02Shappy-lx * + mainpipe -> req0 -> | | secondary_fire? -> + | merge | + + 1386b5c3d02Shappy-lx * + loadpipe0 -> req1 -> | arb | -> req -> + -> | req | -> + + 1396b5c3d02Shappy-lx * + loadpipe1 -> req2 -> | | mshr id -> + | id | + + 1406b5c3d02Shappy-lx * + +-----+ + +-------+ + + 1416b5c3d02Shappy-lx * +---------------------------------------------------------------------+ +-------------------------+ 1426b5c3d02Shappy-lx */ 1436b5c3d02Shappy-lx 1446b5c3d02Shappy-lx// a pipeline reg between MissReq and MissEntry 145d2945707SHuijin Liclass MissReqPipeRegBundle(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheBundle 146d2945707SHuijin Li with HasCircularQueuePtrHelper 147d2945707SHuijin Li { 1486b5c3d02Shappy-lx val req = new MissReq 1496b5c3d02Shappy-lx // this request is about to merge to an existing mshr 1506b5c3d02Shappy-lx val merge = Bool() 1516b5c3d02Shappy-lx // this request is about to allocate a new mshr 1526b5c3d02Shappy-lx val alloc = Bool() 15308b0bc30Shappy-lx val cancel = Bool() 1546b5c3d02Shappy-lx val mshr_id = UInt(log2Up(cfg.nMissEntries).W) 1556b5c3d02Shappy-lx 1566b5c3d02Shappy-lx def reg_valid(): Bool = { 1576b5c3d02Shappy-lx (merge || alloc) 1586b5c3d02Shappy-lx } 1596b5c3d02Shappy-lx 1600d32f713Shappy-lx def matched(new_req: MissReq): Bool = { 1610d32f713Shappy-lx val block_match = get_block(req.addr) === get_block(new_req.addr) 1620d32f713Shappy-lx block_match && reg_valid() && !(req.isFromPrefetch) 1630d32f713Shappy-lx } 1640d32f713Shappy-lx 1650d32f713Shappy-lx def prefetch_late_en(new_req: MissReqWoStoreData, new_req_valid: Bool): Bool = { 1660d32f713Shappy-lx val block_match = get_block(req.addr) === get_block(new_req.addr) 1670d32f713Shappy-lx new_req_valid && alloc && block_match && (req.isFromPrefetch) && !(new_req.isFromPrefetch) 1680d32f713Shappy-lx } 1690d32f713Shappy-lx 1706b5c3d02Shappy-lx def reject_req(new_req: MissReq): Bool = { 1710d32f713Shappy-lx val block_match = get_block(req.addr) === get_block(new_req.addr) 1720d32f713Shappy-lx val alias_match = is_alias_match(req.vaddr, new_req.vaddr) 1730d32f713Shappy-lx val merge_load = (req.isFromLoad || req.isFromStore || req.isFromPrefetch) && new_req.isFromLoad 1740d32f713Shappy-lx // store merge to a store is disabled, sbuffer should avoid this situation, as store to same address should preserver their program order to match memory model 1750d32f713Shappy-lx val merge_store = (req.isFromLoad || req.isFromPrefetch) && new_req.isFromStore 1760d32f713Shappy-lx 1776b5c3d02Shappy-lx val set_match = addr_to_dcache_set(req.vaddr) === addr_to_dcache_set(new_req.vaddr) 178ffd3154dSCharlieLiu 1790d32f713Shappy-lx Mux( 1800d32f713Shappy-lx alloc, 181ffd3154dSCharlieLiu block_match && (!alias_match || !(merge_load || merge_store)), 1820d32f713Shappy-lx false.B 1830d32f713Shappy-lx ) 1846b5c3d02Shappy-lx } 1856b5c3d02Shappy-lx 1866b5c3d02Shappy-lx def merge_req(new_req: MissReq): Bool = { 1876b5c3d02Shappy-lx val block_match = get_block(req.addr) === get_block(new_req.addr) 1880d32f713Shappy-lx val alias_match = is_alias_match(req.vaddr, new_req.vaddr) 1896b5c3d02Shappy-lx val merge_load = (req.isFromLoad || req.isFromStore || req.isFromPrefetch) && new_req.isFromLoad 1906b5c3d02Shappy-lx // store merge to a store is disabled, sbuffer should avoid this situation, as store to same address should preserver their program order to match memory model 1916b5c3d02Shappy-lx val merge_store = (req.isFromLoad || req.isFromPrefetch) && new_req.isFromStore 1920d32f713Shappy-lx Mux( 1930d32f713Shappy-lx alloc, 1940d32f713Shappy-lx block_match && alias_match && (merge_load || merge_store), 1950d32f713Shappy-lx false.B 1960d32f713Shappy-lx ) 1976b5c3d02Shappy-lx } 1986b5c3d02Shappy-lx 199d2945707SHuijin Li def merge_isKeyword(new_req: MissReq): Bool = { 200d2945707SHuijin Li val load_merge_load = merge_req(new_req) && req.isFromLoad && new_req.isFromLoad 201d2945707SHuijin Li val store_merge_load = merge_req(new_req) && req.isFromStore && new_req.isFromLoad 202d2945707SHuijin Li val load_merge_load_use_new_req_isKeyword = isAfter(req.lqIdx, new_req.lqIdx) 203d2945707SHuijin Li val use_new_req_isKeyword = (load_merge_load && load_merge_load_use_new_req_isKeyword) || store_merge_load 204d2945707SHuijin Li Mux ( 205d2945707SHuijin Li use_new_req_isKeyword, 206d2945707SHuijin Li new_req.vaddr(5).asBool, 207d2945707SHuijin Li req.vaddr(5).asBool 208d2945707SHuijin Li ) 209d2945707SHuijin Li } 210d2945707SHuijin Li 211d2945707SHuijin Li def isKeyword(): Bool= { 212d2945707SHuijin Li val alloc_isKeyword = Mux( 213d2945707SHuijin Li alloc, 214d2945707SHuijin Li Mux( 215d2945707SHuijin Li req.isFromLoad, 216d2945707SHuijin Li req.vaddr(5).asBool, 217d2945707SHuijin Li false.B), 218d2945707SHuijin Li false.B) 219d2945707SHuijin Li Mux( 220d2945707SHuijin Li merge_req(req), 221d2945707SHuijin Li merge_isKeyword(req), 222d2945707SHuijin Li alloc_isKeyword 223d2945707SHuijin Li ) 224d2945707SHuijin Li } 2256b5c3d02Shappy-lx // send out acquire as soon as possible 2266b5c3d02Shappy-lx // if a new store miss req is about to merge into this pipe reg, don't send acquire now 2276b5c3d02Shappy-lx def can_send_acquire(valid: Bool, new_req: MissReq): Bool = { 2280d32f713Shappy-lx alloc && !(valid && merge_req(new_req) && new_req.isFromStore) 2296b5c3d02Shappy-lx } 2306b5c3d02Shappy-lx 2316b5c3d02Shappy-lx def get_acquire(l2_pf_store_only: Bool): TLBundleA = { 2326b5c3d02Shappy-lx val acquire = Wire(new TLBundleA(edge.bundle)) 2336b5c3d02Shappy-lx val grow_param = req.req_coh.onAccess(req.cmd)._2 2346b5c3d02Shappy-lx val acquireBlock = edge.AcquireBlock( 2356b5c3d02Shappy-lx fromSource = mshr_id, 2366b5c3d02Shappy-lx toAddress = get_block_addr(req.addr), 2376b5c3d02Shappy-lx lgSize = (log2Up(cfg.blockBytes)).U, 2386b5c3d02Shappy-lx growPermissions = grow_param 2396b5c3d02Shappy-lx )._2 2406b5c3d02Shappy-lx val acquirePerm = edge.AcquirePerm( 2416b5c3d02Shappy-lx fromSource = mshr_id, 2426b5c3d02Shappy-lx toAddress = get_block_addr(req.addr), 2436b5c3d02Shappy-lx lgSize = (log2Up(cfg.blockBytes)).U, 2446b5c3d02Shappy-lx growPermissions = grow_param 2456b5c3d02Shappy-lx )._2 2466b5c3d02Shappy-lx acquire := Mux(req.full_overwrite, acquirePerm, acquireBlock) 2476b5c3d02Shappy-lx // resolve cache alias by L2 2486b5c3d02Shappy-lx acquire.user.lift(AliasKey).foreach(_ := req.vaddr(13, 12)) 249ffc9de54Swakafa // pass vaddr to l2 250ffc9de54Swakafa acquire.user.lift(VaddrKey).foreach(_ := req.vaddr(VAddrBits - 1, blockOffBits)) 251d2945707SHuijin Li 252d2945707SHuijin Li // miss req pipe reg pass keyword to L2, is priority 253d2945707SHuijin Li acquire.echo.lift(IsKeywordKey).foreach(_ := isKeyword()) 254d2945707SHuijin Li 2556b5c3d02Shappy-lx // trigger prefetch 2566b5c3d02Shappy-lx acquire.user.lift(PrefetchKey).foreach(_ := Mux(l2_pf_store_only, req.isFromStore, true.B)) 2576b5c3d02Shappy-lx // req source 2586b5c3d02Shappy-lx when(req.isFromLoad) { 2596b5c3d02Shappy-lx acquire.user.lift(ReqSourceKey).foreach(_ := MemReqSource.CPULoadData.id.U) 2606b5c3d02Shappy-lx }.elsewhen(req.isFromStore) { 2616b5c3d02Shappy-lx acquire.user.lift(ReqSourceKey).foreach(_ := MemReqSource.CPUStoreData.id.U) 2626b5c3d02Shappy-lx }.elsewhen(req.isFromAMO) { 2636b5c3d02Shappy-lx acquire.user.lift(ReqSourceKey).foreach(_ := MemReqSource.CPUAtomicData.id.U) 2646b5c3d02Shappy-lx }.otherwise { 2656b5c3d02Shappy-lx acquire.user.lift(ReqSourceKey).foreach(_ := MemReqSource.L1DataPrefetch.id.U) 2666b5c3d02Shappy-lx } 2676b5c3d02Shappy-lx 2686b5c3d02Shappy-lx acquire 2696b5c3d02Shappy-lx } 2701461d8f8SCharlieLiu 2711461d8f8SCharlieLiu def block_match(release_addr: UInt): Bool = { 2721461d8f8SCharlieLiu reg_valid() && get_block(req.addr) === get_block(release_addr) 2731461d8f8SCharlieLiu } 2746b5c3d02Shappy-lx} 2756b5c3d02Shappy-lx 276dc4fac13SCharlieLiuclass CMOUnit(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule { 277dc4fac13SCharlieLiu val io = IO(new Bundle() { 278dc4fac13SCharlieLiu val req = Flipped(DecoupledIO(new CMOReq)) 279dc4fac13SCharlieLiu val req_chanA = DecoupledIO(new TLBundleA(edge.bundle)) 280dc4fac13SCharlieLiu val resp_chanD = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 281dc4fac13SCharlieLiu val resp_to_lsq = DecoupledIO(new CMOResp) 282dc4fac13SCharlieLiu }) 283dc4fac13SCharlieLiu 284dc4fac13SCharlieLiu val s_idle :: s_sreq :: s_wresp :: s_lsq_resp :: Nil = Enum(4) 285dc4fac13SCharlieLiu val state = RegInit(s_idle) 286dc4fac13SCharlieLiu val state_next = WireInit(state) 287dc4fac13SCharlieLiu val req = RegEnable(io.req.bits, io.req.fire) 2881abade56SAnzo val nderr = RegInit(false.B) 289dc4fac13SCharlieLiu 290dc4fac13SCharlieLiu state := state_next 291dc4fac13SCharlieLiu 292dc4fac13SCharlieLiu switch (state) { 293dc4fac13SCharlieLiu is(s_idle) { 294dc4fac13SCharlieLiu when (io.req.fire) { 295dc4fac13SCharlieLiu state_next := s_sreq 2961abade56SAnzo nderr := false.B 297dc4fac13SCharlieLiu } 298dc4fac13SCharlieLiu } 299dc4fac13SCharlieLiu is(s_sreq) { 300dc4fac13SCharlieLiu when (io.req_chanA.fire) { 301dc4fac13SCharlieLiu state_next := s_wresp 302dc4fac13SCharlieLiu } 303dc4fac13SCharlieLiu } 304dc4fac13SCharlieLiu is(s_wresp) { 305dc4fac13SCharlieLiu when (io.resp_chanD.fire) { 306dc4fac13SCharlieLiu state_next := s_lsq_resp 3071abade56SAnzo nderr := io.resp_chanD.bits.denied || io.resp_chanD.bits.corrupt 308dc4fac13SCharlieLiu } 309dc4fac13SCharlieLiu } 310dc4fac13SCharlieLiu is(s_lsq_resp) { 311dc4fac13SCharlieLiu when (io.resp_to_lsq.fire) { 312dc4fac13SCharlieLiu state_next := s_idle 313dc4fac13SCharlieLiu } 314dc4fac13SCharlieLiu } 315dc4fac13SCharlieLiu } 316dc4fac13SCharlieLiu 317dc4fac13SCharlieLiu io.req.ready := state === s_idle 318dc4fac13SCharlieLiu 319dc4fac13SCharlieLiu io.req_chanA.valid := state === s_sreq 320dc4fac13SCharlieLiu io.req_chanA.bits := edge.CacheBlockOperation( 321dc4fac13SCharlieLiu fromSource = (cfg.nMissEntries + 1).U, 322dc4fac13SCharlieLiu toAddress = req.address, 323dc4fac13SCharlieLiu lgSize = (log2Up(cfg.blockBytes)).U, 324dc4fac13SCharlieLiu opcode = req.opcode 325dc4fac13SCharlieLiu )._2 326dc4fac13SCharlieLiu 327dc4fac13SCharlieLiu io.resp_chanD.ready := state === s_wresp 328dc4fac13SCharlieLiu 329dc4fac13SCharlieLiu io.resp_to_lsq.valid := state === s_lsq_resp 330dc4fac13SCharlieLiu io.resp_to_lsq.bits.address := req.address 3311abade56SAnzo io.resp_to_lsq.bits.nderr := nderr 332dc4fac13SCharlieLiu 333dc4fac13SCharlieLiu assert(!(state =/= s_idle && io.req.valid)) 334dc4fac13SCharlieLiu assert(!(state =/= s_wresp && io.resp_chanD.valid)) 335dc4fac13SCharlieLiu} 336dc4fac13SCharlieLiu 33708b0bc30Shappy-lxclass MissEntry(edge: TLEdgeOut, reqNum: Int)(implicit p: Parameters) extends DCacheModule 338d2945707SHuijin Li with HasCircularQueuePtrHelper 339d2945707SHuijin Li { 340ad3ba452Szhanglinjuan val io = IO(new Bundle() { 341f57f7f2aSYangyu Chen val hartId = Input(UInt(hartIdLen.W)) 3421f0e2dc7SJiawei Lin // MSHR ID 343ad3ba452Szhanglinjuan val id = Input(UInt(log2Up(cfg.nMissEntries).W)) 3441f0e2dc7SJiawei Lin // client requests 345935edac4STang Haojin // MSHR update request, MSHR state and addr will be updated when req.fire 346e771db6cSWilliam Wang val req = Flipped(ValidIO(new MissReqWoStoreData)) 34708b0bc30Shappy-lx val wbq_block_miss_req = Input(Bool()) 3486b5c3d02Shappy-lx // pipeline reg 3496b5c3d02Shappy-lx val miss_req_pipe_reg = Input(new MissReqPipeRegBundle(edge)) 35096b1e495SWilliam Wang // allocate this entry for new req 35196b1e495SWilliam Wang val primary_valid = Input(Bool()) 3521f0e2dc7SJiawei Lin // this entry is free and can be allocated to new reqs 3531f0e2dc7SJiawei Lin val primary_ready = Output(Bool()) 3541f0e2dc7SJiawei Lin // this entry is busy, but it can merge the new req 3551f0e2dc7SJiawei Lin val secondary_ready = Output(Bool()) 3561f0e2dc7SJiawei Lin // this entry is busy and it can not merge the new req 3571f0e2dc7SJiawei Lin val secondary_reject = Output(Bool()) 358fa9ac9b6SWilliam Wang // way selected for replacing, used to support plru update 3591f0e2dc7SJiawei Lin // bus 3601f0e2dc7SJiawei Lin val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle)) 3611f0e2dc7SJiawei Lin val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 3621f0e2dc7SJiawei Lin val mem_finish = DecoupledIO(new TLBundleE(edge.bundle)) 3631f0e2dc7SJiawei Lin 36408b0bc30Shappy-lx val queryME = Vec(reqNum, Flipped(new DCacheMEQueryIOBundle)) 36508b0bc30Shappy-lx 366ffd3154dSCharlieLiu // send refill info to load queue, useless now 367fa9ac9b6SWilliam Wang val refill_to_ldq = ValidIO(new Refill) 368fa9ac9b6SWilliam Wang 369ad3ba452Szhanglinjuan // replace pipe 370ffd3154dSCharlieLiu val l2_hint = Input(Valid(new L2ToL1Hint())) // Hint from L2 Cache 371ad3ba452Szhanglinjuan 372ad3ba452Szhanglinjuan // main pipe: amo miss 373ad3ba452Szhanglinjuan val main_pipe_req = DecoupledIO(new MainPipeReq) 374ad3ba452Szhanglinjuan val main_pipe_resp = Input(Bool()) 375ffd3154dSCharlieLiu val main_pipe_refill_resp = Input(Bool()) 376ffd3154dSCharlieLiu val main_pipe_replay = Input(Bool()) 377ffd3154dSCharlieLiu 378ffd3154dSCharlieLiu // for main pipe s2 379ffd3154dSCharlieLiu val refill_info = ValidIO(new MissQueueRefillInfo) 380ad3ba452Szhanglinjuan 3811f0e2dc7SJiawei Lin val block_addr = ValidIO(UInt(PAddrBits.W)) 382ad3ba452Szhanglinjuan 3831461d8f8SCharlieLiu val req_addr = ValidIO(UInt(PAddrBits.W)) 3841461d8f8SCharlieLiu 385683c1411Shappy-lx val req_handled_by_this_entry = Output(Bool()) 386683c1411Shappy-lx 387683c1411Shappy-lx val forwardInfo = Output(new MissEntryForwardIO) 388f1d78cf7SLinJiawei val l2_pf_store_only = Input(Bool()) 389d2b20d1aSTang Haojin 3906b5c3d02Shappy-lx // whether the pipeline reg has send out an acquire 3916b5c3d02Shappy-lx val acquire_fired_by_pipe_reg = Input(Bool()) 3920d32f713Shappy-lx val memSetPattenDetected = Input(Bool()) 3936b5c3d02Shappy-lx 394d2b20d1aSTang Haojin val perf_pending_prefetch = Output(Bool()) 395d2b20d1aSTang Haojin val perf_pending_normal = Output(Bool()) 396d2b20d1aSTang Haojin 397d2b20d1aSTang Haojin val rob_head_query = new DCacheBundle { 398d2b20d1aSTang Haojin val vaddr = Input(UInt(VAddrBits.W)) 399d2b20d1aSTang Haojin val query_valid = Input(Bool()) 400d2b20d1aSTang Haojin 401d2b20d1aSTang Haojin val resp = Output(Bool()) 402d2b20d1aSTang Haojin 403d2b20d1aSTang Haojin def hit(e_vaddr: UInt): Bool = { 404d2b20d1aSTang Haojin require(e_vaddr.getWidth == VAddrBits) 405d2b20d1aSTang Haojin query_valid && vaddr(VAddrBits - 1, DCacheLineOffset) === e_vaddr(VAddrBits - 1, DCacheLineOffset) 406d2b20d1aSTang Haojin } 407d2b20d1aSTang Haojin } 408d2b20d1aSTang Haojin 409d2b20d1aSTang Haojin val latency_monitor = new DCacheBundle { 410d2b20d1aSTang Haojin val load_miss_refilling = Output(Bool()) 411d2b20d1aSTang Haojin val store_miss_refilling = Output(Bool()) 412d2b20d1aSTang Haojin val amo_miss_refilling = Output(Bool()) 413d2b20d1aSTang Haojin val pf_miss_refilling = Output(Bool()) 414d2b20d1aSTang Haojin } 4150d32f713Shappy-lx 4160d32f713Shappy-lx val prefetch_info = new DCacheBundle { 4170d32f713Shappy-lx val late_prefetch = Output(Bool()) 4180d32f713Shappy-lx } 4190d32f713Shappy-lx val nMaxPrefetchEntry = Input(UInt(64.W)) 4200d32f713Shappy-lx val matched = Output(Bool()) 421e836c770SZhaoyang You val l1Miss = Output(Bool()) 4221f0e2dc7SJiawei Lin }) 4231f0e2dc7SJiawei Lin 42496b1e495SWilliam Wang assert(!RegNext(io.primary_valid && !io.primary_ready)) 42596b1e495SWilliam Wang 426e771db6cSWilliam Wang val req = Reg(new MissReqWoStoreData) 427d2b20d1aSTang Haojin val req_primary_fire = Reg(new MissReqWoStoreData) // for perf use 428c731e79fSWilliam Wang val req_store_mask = Reg(UInt(cfg.blockBytes.W)) 4291f0e2dc7SJiawei Lin val req_valid = RegInit(false.B) 430ad3ba452Szhanglinjuan val set = addr_to_dcache_set(req.vaddr) 431d2945707SHuijin Li // initial keyword 432d2945707SHuijin Li val isKeyword = RegInit(false.B) 4331f0e2dc7SJiawei Lin 4346b5c3d02Shappy-lx val miss_req_pipe_reg_bits = io.miss_req_pipe_reg.req 4356b5c3d02Shappy-lx 4366b5c3d02Shappy-lx val input_req_is_prefetch = isPrefetch(miss_req_pipe_reg_bits.cmd) 4373af6aa6eSWilliam Wang 4381f0e2dc7SJiawei Lin val s_acquire = RegInit(true.B) 4391f0e2dc7SJiawei Lin val s_grantack = RegInit(true.B) 440ad3ba452Szhanglinjuan val s_mainpipe_req = RegInit(true.B) 441ad3ba452Szhanglinjuan 4421f0e2dc7SJiawei Lin val w_grantfirst = RegInit(true.B) 4431f0e2dc7SJiawei Lin val w_grantlast = RegInit(true.B) 444ad3ba452Szhanglinjuan val w_mainpipe_resp = RegInit(true.B) 445ffd3154dSCharlieLiu val w_refill_resp = RegInit(true.B) 446ffd3154dSCharlieLiu val w_l2hint = RegInit(true.B) 4471f0e2dc7SJiawei Lin 448ffd3154dSCharlieLiu val mainpipe_req_fired = RegInit(true.B) 449ffd3154dSCharlieLiu 450ffd3154dSCharlieLiu val release_entry = s_grantack && w_mainpipe_resp && w_refill_resp 4511f0e2dc7SJiawei Lin 4521f0e2dc7SJiawei Lin val acquire_not_sent = !s_acquire && !io.mem_acquire.ready 45369790076Szhanglinjuan val data_not_refilled = !w_grantfirst 4541f0e2dc7SJiawei Lin 455026615fcSWilliam Wang val error = RegInit(false.B) 4563af6aa6eSWilliam Wang val prefetch = RegInit(false.B) 4573af6aa6eSWilliam Wang val access = RegInit(false.B) 458026615fcSWilliam Wang 4591f0e2dc7SJiawei Lin val should_refill_data_reg = Reg(Bool()) 4601f0e2dc7SJiawei Lin val should_refill_data = WireInit(should_refill_data_reg) 4611f0e2dc7SJiawei Lin 4626005a7e2Shappy-lx val should_replace = RegInit(false.B) 4636005a7e2Shappy-lx 464c731e79fSWilliam Wang val full_overwrite = Reg(Bool()) 4651f0e2dc7SJiawei Lin 4661f0e2dc7SJiawei Lin val (_, _, refill_done, refill_count) = edge.count(io.mem_grant) 4671f0e2dc7SJiawei Lin val grant_param = Reg(UInt(TLPermissions.bdWidth.W)) 4681f0e2dc7SJiawei Lin 469c731e79fSWilliam Wang // refill data with store data, this reg will be used to store: 470c731e79fSWilliam Wang // 1. store data (if needed), before l2 refill data 471c731e79fSWilliam Wang // 2. store data and l2 refill data merged result (i.e. new cacheline taht will be write to data array) 472c731e79fSWilliam Wang val refill_and_store_data = Reg(Vec(blockRows, UInt(rowBits.W))) 473c731e79fSWilliam Wang // raw data refilled to l1 by l2 474c731e79fSWilliam Wang val refill_data_raw = Reg(Vec(blockBytes/beatBytes, UInt(beatBits.W))) 475c731e79fSWilliam Wang 476c731e79fSWilliam Wang // allocate current miss queue entry for a miss req 47708b0bc30Shappy-lx val primary_fire = WireInit(io.req.valid && io.primary_ready && io.primary_valid && !io.req.bits.cancel && !io.wbq_block_miss_req) 47808b0bc30Shappy-lx val primary_accept = WireInit(io.req.valid && io.primary_ready && io.primary_valid && !io.req.bits.cancel) 479c731e79fSWilliam Wang // merge miss req to current miss queue entry 48008b0bc30Shappy-lx val secondary_fire = WireInit(io.req.valid && io.secondary_ready && !io.req.bits.cancel && !io.wbq_block_miss_req) 48108b0bc30Shappy-lx val secondary_accept = WireInit(io.req.valid && io.secondary_ready && !io.req.bits.cancel) 482c731e79fSWilliam Wang 48308b0bc30Shappy-lx val req_handled_by_this_entry = primary_accept || secondary_accept 484683c1411Shappy-lx 485d2b20d1aSTang Haojin // for perf use 486d2b20d1aSTang Haojin val secondary_fired = RegInit(false.B) 487d2b20d1aSTang Haojin 488d2b20d1aSTang Haojin io.perf_pending_prefetch := req_valid && prefetch && !secondary_fired 489d2b20d1aSTang Haojin io.perf_pending_normal := req_valid && (!prefetch || secondary_fired) 490d2b20d1aSTang Haojin 491d2b20d1aSTang Haojin io.rob_head_query.resp := io.rob_head_query.hit(req.vaddr) && req_valid 492d2b20d1aSTang Haojin 493683c1411Shappy-lx io.req_handled_by_this_entry := req_handled_by_this_entry 494683c1411Shappy-lx 495a98b054bSWilliam Wang when (release_entry && req_valid) { 496a98b054bSWilliam Wang req_valid := false.B 497a98b054bSWilliam Wang } 498a98b054bSWilliam Wang 49908b0bc30Shappy-lx when (io.miss_req_pipe_reg.alloc && !io.miss_req_pipe_reg.cancel) { 5006b5c3d02Shappy-lx assert(RegNext(primary_fire), "after 1 cycle of primary_fire, entry will be allocated") 5011f0e2dc7SJiawei Lin req_valid := true.B 5021f0e2dc7SJiawei Lin 5036b5c3d02Shappy-lx req := miss_req_pipe_reg_bits.toMissReqWoStoreData() 5046b5c3d02Shappy-lx req_primary_fire := miss_req_pipe_reg_bits.toMissReqWoStoreData() 5056b5c3d02Shappy-lx req.addr := get_block_addr(miss_req_pipe_reg_bits.addr) 506d2945707SHuijin Li //only load miss need keyword 507d2945707SHuijin Li isKeyword := Mux(miss_req_pipe_reg_bits.isFromLoad, miss_req_pipe_reg_bits.vaddr(5).asBool,false.B) 5086b5c3d02Shappy-lx 5096b5c3d02Shappy-lx s_acquire := io.acquire_fired_by_pipe_reg 5101f0e2dc7SJiawei Lin s_grantack := false.B 511ffd3154dSCharlieLiu s_mainpipe_req := false.B 512ad3ba452Szhanglinjuan 5131f0e2dc7SJiawei Lin w_grantfirst := false.B 5141f0e2dc7SJiawei Lin w_grantlast := false.B 515ffd3154dSCharlieLiu w_l2hint := false.B 516ffd3154dSCharlieLiu mainpipe_req_fired := false.B 517ad3ba452Szhanglinjuan 5186b5c3d02Shappy-lx when(miss_req_pipe_reg_bits.isFromStore) { 5196b5c3d02Shappy-lx req_store_mask := miss_req_pipe_reg_bits.store_mask 5206b5c3d02Shappy-lx for (i <- 0 until blockRows) { 5216b5c3d02Shappy-lx refill_and_store_data(i) := miss_req_pipe_reg_bits.store_data(rowBits * (i + 1) - 1, rowBits * i) 5226b5c3d02Shappy-lx } 5236b5c3d02Shappy-lx } 5246b5c3d02Shappy-lx full_overwrite := miss_req_pipe_reg_bits.isFromStore && miss_req_pipe_reg_bits.full_overwrite 525c731e79fSWilliam Wang 5266b5c3d02Shappy-lx when (!miss_req_pipe_reg_bits.isFromAMO) { 52754e42658SWilliam Wang w_refill_resp := false.B 528ad3ba452Szhanglinjuan } 529ad3ba452Szhanglinjuan 5306b5c3d02Shappy-lx when (miss_req_pipe_reg_bits.isFromAMO) { 531ad3ba452Szhanglinjuan w_mainpipe_resp := false.B 532ad3ba452Szhanglinjuan } 5331f0e2dc7SJiawei Lin 5346b5c3d02Shappy-lx should_refill_data_reg := miss_req_pipe_reg_bits.isFromLoad 535026615fcSWilliam Wang error := false.B 5360d32f713Shappy-lx prefetch := input_req_is_prefetch && !io.miss_req_pipe_reg.prefetch_late_en(io.req.bits, io.req.valid) 5373af6aa6eSWilliam Wang access := false.B 538d2b20d1aSTang Haojin secondary_fired := false.B 5391f0e2dc7SJiawei Lin } 5401f0e2dc7SJiawei Lin 54108b0bc30Shappy-lx when (io.miss_req_pipe_reg.merge && !io.miss_req_pipe_reg.cancel) { 5426b5c3d02Shappy-lx assert(RegNext(secondary_fire) || RegNext(RegNext(primary_fire)), "after 1 cycle of secondary_fire or 2 cycle of primary_fire, entry will be merged") 5436b5c3d02Shappy-lx assert(miss_req_pipe_reg_bits.req_coh.state <= req.req_coh.state || (prefetch && !access)) 5446b5c3d02Shappy-lx assert(!(miss_req_pipe_reg_bits.isFromAMO || req.isFromAMO)) 5451f0e2dc7SJiawei Lin // use the most uptodate meta 5466b5c3d02Shappy-lx req.req_coh := miss_req_pipe_reg_bits.req_coh 5471f0e2dc7SJiawei Lin 548d2945707SHuijin Li isKeyword := Mux( 54905d833a8SHuijin Li before_req_sent_can_merge(miss_req_pipe_reg_bits), 55005d833a8SHuijin Li before_req_sent_merge_iskeyword(miss_req_pipe_reg_bits), 551d2945707SHuijin Li isKeyword) 5520d32f713Shappy-lx assert(!miss_req_pipe_reg_bits.isFromPrefetch, "can not merge a prefetch req, late prefetch should always be ignored!") 5530d32f713Shappy-lx 5546b5c3d02Shappy-lx when (miss_req_pipe_reg_bits.isFromStore) { 5556b5c3d02Shappy-lx req := miss_req_pipe_reg_bits 5566b5c3d02Shappy-lx req.addr := get_block_addr(miss_req_pipe_reg_bits.addr) 5576b5c3d02Shappy-lx req_store_mask := miss_req_pipe_reg_bits.store_mask 5586b5c3d02Shappy-lx for (i <- 0 until blockRows) { 5596b5c3d02Shappy-lx refill_and_store_data(i) := miss_req_pipe_reg_bits.store_data(rowBits * (i + 1) - 1, rowBits * i) 5606b5c3d02Shappy-lx } 5616b5c3d02Shappy-lx full_overwrite := miss_req_pipe_reg_bits.isFromStore && miss_req_pipe_reg_bits.full_overwrite 5620d32f713Shappy-lx assert(is_alias_match(req.vaddr, miss_req_pipe_reg_bits.vaddr), "alias bits should be the same when merging store") 5631f0e2dc7SJiawei Lin } 5641f0e2dc7SJiawei Lin 5656b5c3d02Shappy-lx should_refill_data := should_refill_data_reg || miss_req_pipe_reg_bits.isFromLoad 5661f0e2dc7SJiawei Lin should_refill_data_reg := should_refill_data 5673af6aa6eSWilliam Wang when (!input_req_is_prefetch) { 5683af6aa6eSWilliam Wang access := true.B // when merge non-prefetch req, set access bit 5693af6aa6eSWilliam Wang } 570d2b20d1aSTang Haojin secondary_fired := true.B 5711f0e2dc7SJiawei Lin } 5721f0e2dc7SJiawei Lin 573935edac4STang Haojin when (io.mem_acquire.fire) { 5741f0e2dc7SJiawei Lin s_acquire := true.B 5751f0e2dc7SJiawei Lin } 5761f0e2dc7SJiawei Lin 577c731e79fSWilliam Wang // merge data refilled by l2 and store data, update miss queue entry, gen refill_req 5781f0e2dc7SJiawei Lin val new_data = Wire(Vec(blockRows, UInt(rowBits.W))) 5791f0e2dc7SJiawei Lin val new_mask = Wire(Vec(blockRows, UInt(rowBytes.W))) 580c731e79fSWilliam Wang // merge refilled data and store data (if needed) 5811f0e2dc7SJiawei Lin def mergePutData(old_data: UInt, new_data: UInt, wmask: UInt): UInt = { 5821f0e2dc7SJiawei Lin val full_wmask = FillInterleaved(8, wmask) 5831f0e2dc7SJiawei Lin (~full_wmask & old_data | full_wmask & new_data) 5841f0e2dc7SJiawei Lin } 5851f0e2dc7SJiawei Lin for (i <- 0 until blockRows) { 586c731e79fSWilliam Wang // new_data(i) := req.store_data(rowBits * (i + 1) - 1, rowBits * i) 587c731e79fSWilliam Wang new_data(i) := refill_and_store_data(i) 5881f0e2dc7SJiawei Lin // we only need to merge data for Store 58900575ac8SWilliam Wang new_mask(i) := Mux(req.isFromStore, req_store_mask(rowBytes * (i + 1) - 1, rowBytes * i), 0.U) 5901f0e2dc7SJiawei Lin } 591c731e79fSWilliam Wang 5921f0e2dc7SJiawei Lin val hasData = RegInit(true.B) 5931f0e2dc7SJiawei Lin val isDirty = RegInit(false.B) 594935edac4STang Haojin when (io.mem_grant.fire) { 5951f0e2dc7SJiawei Lin w_grantfirst := true.B 5961f0e2dc7SJiawei Lin grant_param := io.mem_grant.bits.param 5971f0e2dc7SJiawei Lin when (edge.hasData(io.mem_grant.bits)) { 5981f0e2dc7SJiawei Lin // GrantData 599d2945707SHuijin Li when (isKeyword) { 600d2945707SHuijin Li for (i <- 0 until beatRows) { 601d2945707SHuijin Li val idx = ((refill_count << log2Floor(beatRows)) + i.U) ^ 4.U 602d2945707SHuijin Li val grant_row = io.mem_grant.bits.data(rowBits * (i + 1) - 1, rowBits * i) 603d2945707SHuijin Li refill_and_store_data(idx) := mergePutData(grant_row, new_data(idx), new_mask(idx)) 604d2945707SHuijin Li } 605d2945707SHuijin Li } 606d2945707SHuijin Li .otherwise{ 6071f0e2dc7SJiawei Lin for (i <- 0 until beatRows) { 6081f0e2dc7SJiawei Lin val idx = (refill_count << log2Floor(beatRows)) + i.U 6091f0e2dc7SJiawei Lin val grant_row = io.mem_grant.bits.data(rowBits * (i + 1) - 1, rowBits * i) 610c731e79fSWilliam Wang refill_and_store_data(idx) := mergePutData(grant_row, new_data(idx), new_mask(idx)) 6111f0e2dc7SJiawei Lin } 612d2945707SHuijin Li } 6131f0e2dc7SJiawei Lin w_grantlast := w_grantlast || refill_done 6141f0e2dc7SJiawei Lin hasData := true.B 6151f0e2dc7SJiawei Lin }.otherwise { 6161f0e2dc7SJiawei Lin // Grant 6171f0e2dc7SJiawei Lin assert(full_overwrite) 6181f0e2dc7SJiawei Lin for (i <- 0 until blockRows) { 619c731e79fSWilliam Wang refill_and_store_data(i) := new_data(i) 6201f0e2dc7SJiawei Lin } 6211f0e2dc7SJiawei Lin w_grantlast := true.B 6221f0e2dc7SJiawei Lin hasData := false.B 6231f0e2dc7SJiawei Lin } 6241f0e2dc7SJiawei Lin 625026615fcSWilliam Wang error := io.mem_grant.bits.denied || io.mem_grant.bits.corrupt || error 626026615fcSWilliam Wang 627d2945707SHuijin Li refill_data_raw(refill_count ^ isKeyword) := io.mem_grant.bits.data 6281f0e2dc7SJiawei Lin isDirty := io.mem_grant.bits.echo.lift(DirtyKey).getOrElse(false.B) 6291f0e2dc7SJiawei Lin } 6301f0e2dc7SJiawei Lin 631935edac4STang Haojin when (io.mem_finish.fire) { 6321f0e2dc7SJiawei Lin s_grantack := true.B 6331f0e2dc7SJiawei Lin } 6341f0e2dc7SJiawei Lin 635935edac4STang Haojin when (io.main_pipe_req.fire) { 636ad3ba452Szhanglinjuan s_mainpipe_req := true.B 637ffd3154dSCharlieLiu mainpipe_req_fired := true.B 638ffd3154dSCharlieLiu } 639ffd3154dSCharlieLiu 640ffd3154dSCharlieLiu when (io.main_pipe_replay) { 641ffd3154dSCharlieLiu s_mainpipe_req := false.B 642ad3ba452Szhanglinjuan } 643ad3ba452Szhanglinjuan 644ad3ba452Szhanglinjuan when (io.main_pipe_resp) { 645ad3ba452Szhanglinjuan w_mainpipe_resp := true.B 646ad3ba452Szhanglinjuan } 6471f0e2dc7SJiawei Lin 648ffd3154dSCharlieLiu when(io.main_pipe_refill_resp) { 649ffd3154dSCharlieLiu w_refill_resp := true.B 650ffd3154dSCharlieLiu } 651ffd3154dSCharlieLiu 652ffd3154dSCharlieLiu when (io.l2_hint.valid) { 653ffd3154dSCharlieLiu w_l2hint := true.B 654ffd3154dSCharlieLiu } 655ffd3154dSCharlieLiu 65626360b3cSWilliam Wang def before_req_sent_can_merge(new_req: MissReqWoStoreData): Bool = { 65708b0bc30Shappy-lx // acquire_not_sent && (new_req.isFromLoad || new_req.isFromStore) 65808b0bc30Shappy-lx 65908b0bc30Shappy-lx // Since most acquire requests have been issued from pipe_reg, 66008b0bc30Shappy-lx // the number of such merge situations is currently small, 66108b0bc30Shappy-lx // So dont Merge anything for better timing. 66208b0bc30Shappy-lx false.B 6631f0e2dc7SJiawei Lin } 6641f0e2dc7SJiawei Lin 665e771db6cSWilliam Wang def before_data_refill_can_merge(new_req: MissReqWoStoreData): Bool = { 66608b0bc30Shappy-lx data_not_refilled && new_req.isFromLoad 6671f0e2dc7SJiawei Lin } 6681f0e2dc7SJiawei Lin 66900575ac8SWilliam Wang // Note that late prefetch will be ignored 67000575ac8SWilliam Wang 671e771db6cSWilliam Wang def should_merge(new_req: MissReqWoStoreData): Bool = { 67269790076Szhanglinjuan val block_match = get_block(req.addr) === get_block(new_req.addr) 6730d32f713Shappy-lx val alias_match = is_alias_match(req.vaddr, new_req.vaddr) 6740d32f713Shappy-lx block_match && alias_match && 675c731e79fSWilliam Wang ( 67626360b3cSWilliam Wang before_req_sent_can_merge(new_req) || 677c731e79fSWilliam Wang before_data_refill_can_merge(new_req) 678c731e79fSWilliam Wang ) 6791f0e2dc7SJiawei Lin } 6801f0e2dc7SJiawei Lin 681d2945707SHuijin Li def before_req_sent_merge_iskeyword(new_req: MissReqWoStoreData): Bool = { 682d2945707SHuijin Li val need_check_isKeyword = acquire_not_sent && req.isFromLoad && new_req.isFromLoad && should_merge(new_req) 683d2945707SHuijin Li val use_new_req_isKeyword = isAfter(req.lqIdx, new_req.lqIdx) 684d2945707SHuijin Li Mux( 685d2945707SHuijin Li need_check_isKeyword, 686d2945707SHuijin Li Mux( 687d2945707SHuijin Li use_new_req_isKeyword, 688d2945707SHuijin Li new_req.vaddr(5).asBool, 689d2945707SHuijin Li req.vaddr(5).asBool 690d2945707SHuijin Li ), 691d2945707SHuijin Li isKeyword 692d2945707SHuijin Li ) 693d2945707SHuijin Li } 694d2945707SHuijin Li 695935edac4STang Haojin // store can be merged before io.mem_acquire.fire 696935edac4STang Haojin // store can not be merged the cycle that io.mem_acquire.fire 697935edac4STang Haojin // load can be merged before io.mem_grant.fire 698c731e79fSWilliam Wang // 699c731e79fSWilliam Wang // TODO: merge store if possible? mem_acquire may need to be re-issued, 700c731e79fSWilliam Wang // but sbuffer entry can be freed 701e771db6cSWilliam Wang def should_reject(new_req: MissReqWoStoreData): Bool = { 70269790076Szhanglinjuan val block_match = get_block(req.addr) === get_block(new_req.addr) 703ad3ba452Szhanglinjuan val set_match = set === addr_to_dcache_set(new_req.vaddr) 7040d32f713Shappy-lx val alias_match = is_alias_match(req.vaddr, new_req.vaddr) 705ad3ba452Szhanglinjuan 706ffd3154dSCharlieLiu req_valid && Mux( 707ad3ba452Szhanglinjuan block_match, 7080d32f713Shappy-lx (!before_req_sent_can_merge(new_req) && !before_data_refill_can_merge(new_req)) || !alias_match, 709ffd3154dSCharlieLiu false.B 710ad3ba452Szhanglinjuan ) 7111f0e2dc7SJiawei Lin } 7121f0e2dc7SJiawei Lin 7136b5c3d02Shappy-lx // req_valid will be updated 1 cycle after primary_fire, so next cycle, this entry cannot accept a new req 7145adc4829SYanqin Li when(GatedValidRegNext(io.id >= ((cfg.nMissEntries).U - io.nMaxPrefetchEntry))) { 7150d32f713Shappy-lx // can accept prefetch req 7165adc4829SYanqin Li io.primary_ready := !req_valid && !GatedValidRegNext(primary_fire) 7170d32f713Shappy-lx }.otherwise { 7180d32f713Shappy-lx // cannot accept prefetch req except when a memset patten is detected 7195adc4829SYanqin Li io.primary_ready := !req_valid && (!io.req.bits.isFromPrefetch || io.memSetPattenDetected) && !GatedValidRegNext(primary_fire) 7200d32f713Shappy-lx } 7211f0e2dc7SJiawei Lin io.secondary_ready := should_merge(io.req.bits) 7221f0e2dc7SJiawei Lin io.secondary_reject := should_reject(io.req.bits) 7231f0e2dc7SJiawei Lin 72408b0bc30Shappy-lx // generate primary_ready & secondary_(ready | reject) for each miss request 72508b0bc30Shappy-lx for (i <- 0 until reqNum) { 72608b0bc30Shappy-lx when(GatedValidRegNext(io.id >= ((cfg.nMissEntries).U - io.nMaxPrefetchEntry))) { 72708b0bc30Shappy-lx io.queryME(i).primary_ready := !req_valid && !GatedValidRegNext(primary_fire) 72808b0bc30Shappy-lx }.otherwise { 72908b0bc30Shappy-lx io.queryME(i).primary_ready := !req_valid && !GatedValidRegNext(primary_fire) && 73008b0bc30Shappy-lx (!io.queryME(i).req.bits.isFromPrefetch || io.memSetPattenDetected) 73108b0bc30Shappy-lx } 73208b0bc30Shappy-lx io.queryME(i).secondary_ready := should_merge(io.queryME(i).req.bits) 73308b0bc30Shappy-lx io.queryME(i).secondary_reject := should_reject(io.queryME(i).req.bits) 73408b0bc30Shappy-lx } 73508b0bc30Shappy-lx 7361f0e2dc7SJiawei Lin // should not allocate, merge or reject at the same time 73758a9a40dSTang Haojin assert(RegNext(PopCount(Seq(io.primary_ready, io.secondary_ready, io.secondary_reject)) <= 1.U || !io.req.valid)) 7381f0e2dc7SJiawei Lin 7391f0e2dc7SJiawei Lin val refill_data_splited = WireInit(VecInit(Seq.tabulate(cfg.blockBytes * 8 / l1BusDataWidth)(i => { 740c731e79fSWilliam Wang val data = refill_and_store_data.asUInt 7411f0e2dc7SJiawei Lin data((i + 1) * l1BusDataWidth - 1, i * l1BusDataWidth) 7421f0e2dc7SJiawei Lin }))) 743683c1411Shappy-lx // when granted data is all ready, wakeup lq's miss load 7445adc4829SYanqin Li val refill_to_ldq_en = !w_grantlast && io.mem_grant.fire 7455adc4829SYanqin Li io.refill_to_ldq.valid := GatedValidRegNext(refill_to_ldq_en) 7465adc4829SYanqin Li io.refill_to_ldq.bits.addr := RegEnable(req.addr + ((refill_count ^ isKeyword) << refillOffBits), refill_to_ldq_en) 7475adc4829SYanqin Li io.refill_to_ldq.bits.data := refill_data_splited(RegEnable(refill_count ^ isKeyword, refill_to_ldq_en)) 7485adc4829SYanqin Li io.refill_to_ldq.bits.error := RegEnable(io.mem_grant.bits.corrupt || io.mem_grant.bits.denied, refill_to_ldq_en) 7495adc4829SYanqin Li io.refill_to_ldq.bits.refill_done := RegEnable(refill_done && io.mem_grant.fire, refill_to_ldq_en) 750ad3ba452Szhanglinjuan io.refill_to_ldq.bits.hasdata := hasData 751ad3ba452Szhanglinjuan io.refill_to_ldq.bits.data_raw := refill_data_raw.asUInt 752683c1411Shappy-lx io.refill_to_ldq.bits.id := io.id 7531f0e2dc7SJiawei Lin 7546b5c3d02Shappy-lx // if the entry has a pending merge req, wait for it 7556b5c3d02Shappy-lx // Note: now, only wait for store, because store may acquire T 75608b0bc30Shappy-lx io.mem_acquire.valid := !s_acquire && !(io.miss_req_pipe_reg.merge && !io.miss_req_pipe_reg.cancel && miss_req_pipe_reg_bits.isFromStore) 757ad3ba452Szhanglinjuan val grow_param = req.req_coh.onAccess(req.cmd)._2 7581f0e2dc7SJiawei Lin val acquireBlock = edge.AcquireBlock( 7591f0e2dc7SJiawei Lin fromSource = io.id, 7601f0e2dc7SJiawei Lin toAddress = req.addr, 7611f0e2dc7SJiawei Lin lgSize = (log2Up(cfg.blockBytes)).U, 7621f0e2dc7SJiawei Lin growPermissions = grow_param 7631f0e2dc7SJiawei Lin )._2 7641f0e2dc7SJiawei Lin val acquirePerm = edge.AcquirePerm( 7651f0e2dc7SJiawei Lin fromSource = io.id, 7661f0e2dc7SJiawei Lin toAddress = req.addr, 7671f0e2dc7SJiawei Lin lgSize = (log2Up(cfg.blockBytes)).U, 7681f0e2dc7SJiawei Lin growPermissions = grow_param 7691f0e2dc7SJiawei Lin )._2 7701f0e2dc7SJiawei Lin io.mem_acquire.bits := Mux(full_overwrite, acquirePerm, acquireBlock) 7711f0e2dc7SJiawei Lin // resolve cache alias by L2 7721f0e2dc7SJiawei Lin io.mem_acquire.bits.user.lift(AliasKey).foreach( _ := req.vaddr(13, 12)) 773ffc9de54Swakafa // pass vaddr to l2 774ffc9de54Swakafa io.mem_acquire.bits.user.lift(VaddrKey).foreach( _ := req.vaddr(VAddrBits-1, blockOffBits)) 775d2945707SHuijin Li // pass keyword to L2 776d2945707SHuijin Li io.mem_acquire.bits.echo.lift(IsKeywordKey).foreach(_ := isKeyword) 7771f0e2dc7SJiawei Lin // trigger prefetch 77800575ac8SWilliam Wang io.mem_acquire.bits.user.lift(PrefetchKey).foreach(_ := Mux(io.l2_pf_store_only, req.isFromStore, true.B)) 779d2b20d1aSTang Haojin // req source 780d2b20d1aSTang Haojin when(prefetch && !secondary_fired) { 781d2b20d1aSTang Haojin io.mem_acquire.bits.user.lift(ReqSourceKey).foreach(_ := MemReqSource.L1DataPrefetch.id.U) 782d2b20d1aSTang Haojin }.otherwise { 783d2b20d1aSTang Haojin when(req.isFromStore) { 784d2b20d1aSTang Haojin io.mem_acquire.bits.user.lift(ReqSourceKey).foreach(_ := MemReqSource.CPUStoreData.id.U) 785d2b20d1aSTang Haojin }.elsewhen(req.isFromLoad) { 786d2b20d1aSTang Haojin io.mem_acquire.bits.user.lift(ReqSourceKey).foreach(_ := MemReqSource.CPULoadData.id.U) 787d2b20d1aSTang Haojin }.elsewhen(req.isFromAMO) { 788d2b20d1aSTang Haojin io.mem_acquire.bits.user.lift(ReqSourceKey).foreach(_ := MemReqSource.CPUAtomicData.id.U) 789d2b20d1aSTang Haojin }.otherwise { 790d2b20d1aSTang Haojin io.mem_acquire.bits.user.lift(ReqSourceKey).foreach(_ := MemReqSource.L1DataPrefetch.id.U) 791d2b20d1aSTang Haojin } 792d2b20d1aSTang Haojin } 793ad3ba452Szhanglinjuan require(nSets <= 256) 794ad3ba452Szhanglinjuan 795cd2ff98bShappy-lx // io.mem_grant.ready := !w_grantlast && s_acquire 796cd2ff98bShappy-lx io.mem_grant.ready := true.B 797cd2ff98bShappy-lx assert(!(io.mem_grant.valid && !(!w_grantlast && s_acquire)), "dcache should always be ready for mem_grant now") 798ad3ba452Szhanglinjuan 799935edac4STang Haojin val grantack = RegEnable(edge.GrantAck(io.mem_grant.bits), io.mem_grant.fire) 800935edac4STang Haojin assert(RegNext(!io.mem_grant.fire || edge.isRequest(io.mem_grant.bits))) 801ad3ba452Szhanglinjuan io.mem_finish.valid := !s_grantack && w_grantfirst 8021f0e2dc7SJiawei Lin io.mem_finish.bits := grantack 8031f0e2dc7SJiawei Lin 804ffd3154dSCharlieLiu // Send mainpipe_req when receive hint from L2 or receive data without hint 805ffd3154dSCharlieLiu io.main_pipe_req.valid := !s_mainpipe_req && (w_l2hint || w_grantlast) 806ad3ba452Szhanglinjuan io.main_pipe_req.bits := DontCare 807ad3ba452Szhanglinjuan io.main_pipe_req.bits.miss := true.B 808ad3ba452Szhanglinjuan io.main_pipe_req.bits.miss_id := io.id 809ad3ba452Szhanglinjuan io.main_pipe_req.bits.probe := false.B 810ad3ba452Szhanglinjuan io.main_pipe_req.bits.source := req.source 811ad3ba452Szhanglinjuan io.main_pipe_req.bits.cmd := req.cmd 812ad3ba452Szhanglinjuan io.main_pipe_req.bits.vaddr := req.vaddr 813ad3ba452Szhanglinjuan io.main_pipe_req.bits.addr := req.addr 814ad3ba452Szhanglinjuan io.main_pipe_req.bits.word_idx := req.word_idx 815ad3ba452Szhanglinjuan io.main_pipe_req.bits.amo_data := req.amo_data 816ad3ba452Szhanglinjuan io.main_pipe_req.bits.amo_mask := req.amo_mask 817*6d8be4c6SCharlieLiu io.main_pipe_req.bits.amo_cmp := req.amo_cmp 818ad3ba452Szhanglinjuan io.main_pipe_req.bits.id := req.id 819ffd3154dSCharlieLiu io.main_pipe_req.bits.pf_source := req.pf_source 820ffd3154dSCharlieLiu io.main_pipe_req.bits.access := access 8211f0e2dc7SJiawei Lin 822ffd3154dSCharlieLiu io.block_addr.valid := req_valid && w_grantlast 8231f0e2dc7SJiawei Lin io.block_addr.bits := req.addr 8241f0e2dc7SJiawei Lin 825038af8f0SCharlie Liu io.req_addr.valid := req_valid 8261461d8f8SCharlieLiu io.req_addr.bits := req.addr 8271461d8f8SCharlieLiu 8281b353fffSCharlie Liu io.refill_info.valid := req_valid && w_grantlast 829ffd3154dSCharlieLiu io.refill_info.bits.store_data := refill_and_store_data.asUInt 830ffd3154dSCharlieLiu io.refill_info.bits.store_mask := ~0.U(blockBytes.W) 831ffd3154dSCharlieLiu io.refill_info.bits.miss_param := grant_param 832ffd3154dSCharlieLiu io.refill_info.bits.miss_dirty := isDirty 8331b0de924SCharlieLiu io.refill_info.bits.error := error 834ffd3154dSCharlieLiu 835ffd3154dSCharlieLiu XSPerfAccumulate("miss_refill_mainpipe_req", io.main_pipe_req.fire) 836ffd3154dSCharlieLiu XSPerfAccumulate("miss_refill_without_hint", io.main_pipe_req.fire && !mainpipe_req_fired && !w_l2hint) 837ffd3154dSCharlieLiu XSPerfAccumulate("miss_refill_replay", io.main_pipe_replay) 8381f0e2dc7SJiawei Lin 839d2945707SHuijin Li val w_grantfirst_forward_info = Mux(isKeyword, w_grantlast, w_grantfirst) 840d2945707SHuijin Li val w_grantlast_forward_info = Mux(isKeyword, w_grantfirst, w_grantlast) 841066ca249Szhanglinjuan io.forwardInfo.inflight := req_valid 842066ca249Szhanglinjuan io.forwardInfo.paddr := req.addr 843066ca249Szhanglinjuan io.forwardInfo.raw_data := refill_and_store_data 844066ca249Szhanglinjuan io.forwardInfo.firstbeat_valid := w_grantfirst_forward_info 845066ca249Szhanglinjuan io.forwardInfo.lastbeat_valid := w_grantlast_forward_info 846066ca249Szhanglinjuan io.forwardInfo.corrupt := error 847683c1411Shappy-lx 8480d32f713Shappy-lx io.matched := req_valid && (get_block(req.addr) === get_block(io.req.bits.addr)) && !prefetch 8490d32f713Shappy-lx io.prefetch_info.late_prefetch := io.req.valid && !(io.req.bits.isFromPrefetch) && req_valid && (get_block(req.addr) === get_block(io.req.bits.addr)) && prefetch 8500d32f713Shappy-lx 8510d32f713Shappy-lx when(io.prefetch_info.late_prefetch) { 8520d32f713Shappy-lx prefetch := false.B 8530d32f713Shappy-lx } 8540d32f713Shappy-lx 855e836c770SZhaoyang You io.l1Miss := req_valid 856d2b20d1aSTang Haojin // refill latency monitor 8575adc4829SYanqin Li val start_counting = GatedValidRegNext(io.mem_acquire.fire) || (GatedValidRegNextN(primary_fire, 2) && s_acquire) 8580d32f713Shappy-lx io.latency_monitor.load_miss_refilling := req_valid && req_primary_fire.isFromLoad && BoolStopWatch(start_counting, io.mem_grant.fire && !refill_done, true, true) 8590d32f713Shappy-lx io.latency_monitor.store_miss_refilling := req_valid && req_primary_fire.isFromStore && BoolStopWatch(start_counting, io.mem_grant.fire && !refill_done, true, true) 8600d32f713Shappy-lx io.latency_monitor.amo_miss_refilling := req_valid && req_primary_fire.isFromAMO && BoolStopWatch(start_counting, io.mem_grant.fire && !refill_done, true, true) 8610d32f713Shappy-lx io.latency_monitor.pf_miss_refilling := req_valid && req_primary_fire.isFromPrefetch && BoolStopWatch(start_counting, io.mem_grant.fire && !refill_done, true, true) 862d2b20d1aSTang Haojin 863a98b054bSWilliam Wang XSPerfAccumulate("miss_req_primary", primary_fire) 864a98b054bSWilliam Wang XSPerfAccumulate("miss_req_merged", secondary_fire) 865ad3ba452Szhanglinjuan XSPerfAccumulate("load_miss_penalty_to_use", 866ad3ba452Szhanglinjuan should_refill_data && 867a98b054bSWilliam Wang BoolStopWatch(primary_fire, io.refill_to_ldq.valid, true) 868ad3ba452Szhanglinjuan ) 869ffd3154dSCharlieLiu XSPerfAccumulate("penalty_between_grantlast_and_release", 870ffd3154dSCharlieLiu BoolStopWatch(!RegNext(w_grantlast) && w_grantlast, release_entry, true) 871ffd3154dSCharlieLiu ) 872935edac4STang Haojin XSPerfAccumulate("main_pipe_penalty", BoolStopWatch(io.main_pipe_req.fire, io.main_pipe_resp)) 8731f0e2dc7SJiawei Lin XSPerfAccumulate("penalty_blocked_by_channel_A", io.mem_acquire.valid && !io.mem_acquire.ready) 8741f0e2dc7SJiawei Lin XSPerfAccumulate("penalty_waiting_for_channel_D", s_acquire && !w_grantlast && !io.mem_grant.valid) 875ad3ba452Szhanglinjuan XSPerfAccumulate("penalty_waiting_for_channel_E", io.mem_finish.valid && !io.mem_finish.ready) 87600575ac8SWilliam Wang XSPerfAccumulate("prefetch_req_primary", primary_fire && io.req.bits.source === DCACHE_PREFETCH_SOURCE.U) 87700575ac8SWilliam Wang XSPerfAccumulate("prefetch_req_merged", secondary_fire && io.req.bits.source === DCACHE_PREFETCH_SOURCE.U) 87808b0bc30Shappy-lx XSPerfAccumulate("can_not_send_acquire_because_of_merging_store", !s_acquire && io.miss_req_pipe_reg.merge && io.miss_req_pipe_reg.cancel && miss_req_pipe_reg_bits.isFromStore) 8791f0e2dc7SJiawei Lin 8805adc4829SYanqin Li val (mshr_penalty_sample, mshr_penalty) = TransactionLatencyCounter(GatedValidRegNextN(primary_fire, 2), release_entry) 881300ded30SWilliam Wang XSPerfHistogram("miss_penalty", mshr_penalty, mshr_penalty_sample, 0, 20, 1, true, true) 882300ded30SWilliam Wang XSPerfHistogram("miss_penalty", mshr_penalty, mshr_penalty_sample, 20, 100, 10, true, false) 8831f0e2dc7SJiawei Lin 88400575ac8SWilliam Wang val load_miss_begin = primary_fire && io.req.bits.isFromLoad 8855adc4829SYanqin Li val refill_finished = GatedValidRegNext(!w_grantlast && refill_done) && should_refill_data 8861f0e2dc7SJiawei Lin val (load_miss_penalty_sample, load_miss_penalty) = TransactionLatencyCounter(load_miss_begin, refill_finished) // not real refill finish time 887300ded30SWilliam Wang XSPerfHistogram("load_miss_penalty_to_use", load_miss_penalty, load_miss_penalty_sample, 0, 20, 1, true, true) 888300ded30SWilliam Wang XSPerfHistogram("load_miss_penalty_to_use", load_miss_penalty, load_miss_penalty_sample, 20, 100, 10, true, false) 889cb900825S周耀阳 (Zhou Yaoyang) XSPerfHistogram("load_miss_penalty_to_use", load_miss_penalty, load_miss_penalty_sample, 100, 400, 30, true, false) 8901f0e2dc7SJiawei Lin 8915adc4829SYanqin Li val (a_to_d_penalty_sample, a_to_d_penalty) = TransactionLatencyCounter(start_counting, GatedValidRegNext(io.mem_grant.fire && refill_done)) 892300ded30SWilliam Wang XSPerfHistogram("a_to_d_penalty", a_to_d_penalty, a_to_d_penalty_sample, 0, 20, 1, true, true) 893300ded30SWilliam Wang XSPerfHistogram("a_to_d_penalty", a_to_d_penalty, a_to_d_penalty_sample, 20, 100, 10, true, false) 8941f0e2dc7SJiawei Lin} 8951f0e2dc7SJiawei Lin 89608b0bc30Shappy-lxclass MissQueue(edge: TLEdgeOut, reqNum: Int)(implicit p: Parameters) extends DCacheModule 897d2945707SHuijin Li with HasPerfEvents 898d2945707SHuijin Li { 8991f0e2dc7SJiawei Lin val io = IO(new Bundle { 900f57f7f2aSYangyu Chen val hartId = Input(UInt(hartIdLen.W)) 9011f0e2dc7SJiawei Lin val req = Flipped(DecoupledIO(new MissReq)) 902683c1411Shappy-lx val resp = Output(new MissResp) 903ad3ba452Szhanglinjuan val refill_to_ldq = ValidIO(new Refill) 9041f0e2dc7SJiawei Lin 905dc4fac13SCharlieLiu // cmo req 906dc4fac13SCharlieLiu val cmo_req = Flipped(DecoupledIO(new CMOReq)) 907dc4fac13SCharlieLiu val cmo_resp = DecoupledIO(new CMOResp) 908dc4fac13SCharlieLiu 90908b0bc30Shappy-lx val queryMQ = Vec(reqNum, Flipped(new DCacheMQQueryIOBundle)) 91008b0bc30Shappy-lx 911ad3ba452Szhanglinjuan val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle)) 9121f0e2dc7SJiawei Lin val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 913ad3ba452Szhanglinjuan val mem_finish = DecoupledIO(new TLBundleE(edge.bundle)) 9141f0e2dc7SJiawei Lin 915ffd3154dSCharlieLiu val l2_hint = Input(Valid(new L2ToL1Hint())) // Hint from L2 Cache 916ad3ba452Szhanglinjuan 917ad3ba452Szhanglinjuan val main_pipe_req = DecoupledIO(new MainPipeReq) 918ffd3154dSCharlieLiu val main_pipe_resp = Flipped(ValidIO(new MainPipeResp)) 919ffd3154dSCharlieLiu 920ffd3154dSCharlieLiu val mainpipe_info = Input(new MainPipeInfoToMQ) 921ffd3154dSCharlieLiu val refill_info = ValidIO(new MissQueueRefillInfo) 9221f0e2dc7SJiawei Lin 9231f0e2dc7SJiawei Lin // block probe 924ad3ba452Szhanglinjuan val probe_addr = Input(UInt(PAddrBits.W)) 9251f0e2dc7SJiawei Lin val probe_block = Output(Bool()) 9261f0e2dc7SJiawei Lin 9277ecd6591SCharlie Liu // block replace when release an addr valid in mshr 9287ecd6591SCharlie Liu val replace_addr = Flipped(ValidIO(UInt(PAddrBits.W))) 9297ecd6591SCharlie Liu val replace_block = Output(Bool()) 9301461d8f8SCharlieLiu 93108b0bc30Shappy-lx // req blocked by wbq 93208b0bc30Shappy-lx val wbq_block_miss_req = Input(Bool()) 93308b0bc30Shappy-lx 9341f0e2dc7SJiawei Lin val full = Output(Bool()) 935ad3ba452Szhanglinjuan 936683c1411Shappy-lx // forward missqueue 937683c1411Shappy-lx val forward = Vec(LoadPipelineWidth, new LduToMissqueueForwardIO) 938f1d78cf7SLinJiawei val l2_pf_store_only = Input(Bool()) 939e50f3145Ssfencevma 9400d32f713Shappy-lx val memSetPattenDetected = Output(Bool()) 9410d32f713Shappy-lx val lqEmpty = Input(Bool()) 9420d32f713Shappy-lx 9430d32f713Shappy-lx val prefetch_info = new Bundle { 9440d32f713Shappy-lx val naive = new Bundle { 9450d32f713Shappy-lx val late_miss_prefetch = Output(Bool()) 9460d32f713Shappy-lx } 9470d32f713Shappy-lx 9480d32f713Shappy-lx val fdp = new Bundle { 9490d32f713Shappy-lx val late_miss_prefetch = Output(Bool()) 9500d32f713Shappy-lx val prefetch_monitor_cnt = Output(Bool()) 9510d32f713Shappy-lx val total_prefetch = Output(Bool()) 9520d32f713Shappy-lx } 9530d32f713Shappy-lx } 9540d32f713Shappy-lx 95560ebee38STang Haojin val debugTopDown = new DCacheTopDownIO 956e836c770SZhaoyang You val l1Miss = Output(Bool()) 9571f0e2dc7SJiawei Lin }) 9581f0e2dc7SJiawei Lin 9591f0e2dc7SJiawei Lin // 128KBL1: FIXME: provide vaddr for l2 9601f0e2dc7SJiawei Lin 96108b0bc30Shappy-lx val entries = Seq.fill(cfg.nMissEntries)(Module(new MissEntry(edge, reqNum))) 962dc4fac13SCharlieLiu val cmo_unit = Module(new CMOUnit(edge)) 9631f0e2dc7SJiawei Lin 9646b5c3d02Shappy-lx val miss_req_pipe_reg = RegInit(0.U.asTypeOf(new MissReqPipeRegBundle(edge))) 9656b5c3d02Shappy-lx val acquire_from_pipereg = Wire(chiselTypeOf(io.mem_acquire)) 966c731e79fSWilliam Wang 967ad3ba452Szhanglinjuan val primary_ready_vec = entries.map(_.io.primary_ready) 968ad3ba452Szhanglinjuan val secondary_ready_vec = entries.map(_.io.secondary_ready) 969ad3ba452Szhanglinjuan val secondary_reject_vec = entries.map(_.io.secondary_reject) 970ad3ba452Szhanglinjuan val probe_block_vec = entries.map { case e => e.io.block_addr.valid && e.io.block_addr.bits === io.probe_addr } 9711f0e2dc7SJiawei Lin 972cd2ff98bShappy-lx val merge = ParallelORR(Cat(secondary_ready_vec ++ Seq(miss_req_pipe_reg.merge_req(io.req.bits)))) 973cd2ff98bShappy-lx val reject = ParallelORR(Cat(secondary_reject_vec ++ Seq(miss_req_pipe_reg.reject_req(io.req.bits)))) 974cd2ff98bShappy-lx val alloc = !reject && !merge && ParallelORR(Cat(primary_ready_vec)) 975ad3ba452Szhanglinjuan val accept = alloc || merge 976ad3ba452Szhanglinjuan 97708b0bc30Shappy-lx // generate req_ready for each miss request for better timing 97808b0bc30Shappy-lx for (i <- 0 until reqNum) { 97908b0bc30Shappy-lx val _primary_ready_vec = entries.map(_.io.queryME(i).primary_ready) 98008b0bc30Shappy-lx val _secondary_ready_vec = entries.map(_.io.queryME(i).secondary_ready) 98108b0bc30Shappy-lx val _secondary_reject_vec = entries.map(_.io.queryME(i).secondary_reject) 98208b0bc30Shappy-lx val _merge = ParallelORR(Cat(_secondary_ready_vec ++ Seq(miss_req_pipe_reg.merge_req(io.queryMQ(i).req.bits)))) 98308b0bc30Shappy-lx val _reject = ParallelORR(Cat(_secondary_reject_vec ++ Seq(miss_req_pipe_reg.reject_req(io.queryMQ(i).req.bits)))) 98408b0bc30Shappy-lx val _alloc = !_reject && !_merge && ParallelORR(Cat(_primary_ready_vec)) 98508b0bc30Shappy-lx val _accept = _alloc || _merge 98608b0bc30Shappy-lx 98708b0bc30Shappy-lx io.queryMQ(i).ready := _accept 98808b0bc30Shappy-lx } 98908b0bc30Shappy-lx 9906b5c3d02Shappy-lx val req_mshr_handled_vec = entries.map(_.io.req_handled_by_this_entry) 9916b5c3d02Shappy-lx // merged to pipeline reg 99258a9a40dSTang Haojin val req_pipeline_reg_handled = miss_req_pipe_reg.merge_req(io.req.bits) && io.req.valid 9936b5c3d02Shappy-lx assert(PopCount(Seq(req_pipeline_reg_handled, VecInit(req_mshr_handled_vec).asUInt.orR)) <= 1.U, "miss req will either go to mshr or pipeline reg") 9946b5c3d02Shappy-lx assert(PopCount(req_mshr_handled_vec) <= 1.U, "Only one mshr can handle a req") 9956b5c3d02Shappy-lx io.resp.id := Mux(!req_pipeline_reg_handled, OHToUInt(req_mshr_handled_vec), miss_req_pipe_reg.mshr_id) 9966b5c3d02Shappy-lx io.resp.handled := Cat(req_mshr_handled_vec).orR || req_pipeline_reg_handled 997fa9ac9b6SWilliam Wang io.resp.merged := merge 9986b5c3d02Shappy-lx 9996b5c3d02Shappy-lx /* MissQueue enq logic is now splitted into 2 cycles 10006b5c3d02Shappy-lx * 10016b5c3d02Shappy-lx */ 10025003e6f8SHuijin Li when(io.req.valid){ 10036b5c3d02Shappy-lx miss_req_pipe_reg.req := io.req.bits 10045003e6f8SHuijin Li } 10055003e6f8SHuijin Li // miss_req_pipe_reg.req := io.req.bits 100608b0bc30Shappy-lx miss_req_pipe_reg.alloc := alloc && io.req.valid && !io.req.bits.cancel && !io.wbq_block_miss_req 100708b0bc30Shappy-lx miss_req_pipe_reg.merge := merge && io.req.valid && !io.req.bits.cancel && !io.wbq_block_miss_req 100808b0bc30Shappy-lx miss_req_pipe_reg.cancel := io.wbq_block_miss_req 10096b5c3d02Shappy-lx miss_req_pipe_reg.mshr_id := io.resp.id 10106b5c3d02Shappy-lx 10116b5c3d02Shappy-lx assert(PopCount(Seq(alloc && io.req.valid, merge && io.req.valid)) <= 1.U, "allocate and merge a mshr in same cycle!") 1012683c1411Shappy-lx 10130d32f713Shappy-lx val source_except_load_cnt = RegInit(0.U(10.W)) 10140d32f713Shappy-lx when(VecInit(req_mshr_handled_vec).asUInt.orR || req_pipeline_reg_handled) { 10150d32f713Shappy-lx when(io.req.bits.isFromLoad) { 10160d32f713Shappy-lx source_except_load_cnt := 0.U 10170d32f713Shappy-lx }.otherwise { 10180d32f713Shappy-lx when(io.req.bits.isFromStore) { 10190d32f713Shappy-lx source_except_load_cnt := source_except_load_cnt + 1.U 10200d32f713Shappy-lx } 10210d32f713Shappy-lx } 10220d32f713Shappy-lx } 10230d32f713Shappy-lx val Threshold = 8 10245adc4829SYanqin Li val memSetPattenDetected = GatedValidRegNext((source_except_load_cnt >= Threshold.U) && io.lqEmpty) 10250d32f713Shappy-lx 10260d32f713Shappy-lx io.memSetPattenDetected := memSetPattenDetected 10270d32f713Shappy-lx 1028683c1411Shappy-lx val forwardInfo_vec = VecInit(entries.map(_.io.forwardInfo)) 1029683c1411Shappy-lx (0 until LoadPipelineWidth).map(i => { 1030683c1411Shappy-lx val id = io.forward(i).mshrid 1031683c1411Shappy-lx val req_valid = io.forward(i).valid 1032683c1411Shappy-lx val paddr = io.forward(i).paddr 1033683c1411Shappy-lx 1034683c1411Shappy-lx val (forward_mshr, forwardData) = forwardInfo_vec(id).forward(req_valid, paddr) 1035683c1411Shappy-lx io.forward(i).forward_result_valid := forwardInfo_vec(id).check(req_valid, paddr) 1036683c1411Shappy-lx io.forward(i).forward_mshr := forward_mshr 1037683c1411Shappy-lx io.forward(i).forwardData := forwardData 1038066ca249Szhanglinjuan io.forward(i).corrupt := RegNext(forwardInfo_vec(id).corrupt) 1039683c1411Shappy-lx }) 1040683c1411Shappy-lx 104158a9a40dSTang Haojin assert(RegNext(PopCount(secondary_ready_vec) <= 1.U || !io.req.valid)) 1042ad3ba452Szhanglinjuan// assert(RegNext(PopCount(secondary_reject_vec) <= 1.U)) 1043ad3ba452Szhanglinjuan // It is possible that one mshr wants to merge a req, while another mshr wants to reject it. 1044ad3ba452Szhanglinjuan // That is, a coming req has the same paddr as that of mshr_0 (merge), 1045ad3ba452Szhanglinjuan // while it has the same set and the same way as mshr_1 (reject). 1046ad3ba452Szhanglinjuan // In this situation, the coming req should be merged by mshr_0 1047ad3ba452Szhanglinjuan// assert(RegNext(PopCount(Seq(merge, reject)) <= 1.U)) 1048ad3ba452Szhanglinjuan 104996b1e495SWilliam Wang def select_valid_one[T <: Bundle]( 105096b1e495SWilliam Wang in: Seq[DecoupledIO[T]], 105196b1e495SWilliam Wang out: DecoupledIO[T], 105296b1e495SWilliam Wang name: Option[String] = None): Unit = { 105396b1e495SWilliam Wang 105496b1e495SWilliam Wang if (name.nonEmpty) { out.suggestName(s"${name.get}_select") } 105596b1e495SWilliam Wang out.valid := Cat(in.map(_.valid)).orR 105696b1e495SWilliam Wang out.bits := ParallelMux(in.map(_.valid) zip in.map(_.bits)) 105796b1e495SWilliam Wang in.map(_.ready := out.ready) 105896b1e495SWilliam Wang assert(!RegNext(out.valid && PopCount(Cat(in.map(_.valid))) > 1.U)) 105996b1e495SWilliam Wang } 106096b1e495SWilliam Wang 10611f0e2dc7SJiawei Lin io.mem_grant.ready := false.B 10621f0e2dc7SJiawei Lin 1063c686adcdSYinan Xu val nMaxPrefetchEntry = Constantin.createRecord(s"nMaxPrefetchEntry${p(XSCoreParamsKey).HartId}", initValue = 14) 1064ad3ba452Szhanglinjuan entries.zipWithIndex.foreach { 1065ad3ba452Szhanglinjuan case (e, i) => 106696b1e495SWilliam Wang val former_primary_ready = if(i == 0) 106796b1e495SWilliam Wang false.B 106896b1e495SWilliam Wang else 106996b1e495SWilliam Wang Cat((0 until i).map(j => entries(j).io.primary_ready)).orR 107096b1e495SWilliam Wang 1071683c1411Shappy-lx e.io.hartId := io.hartId 1072ad3ba452Szhanglinjuan e.io.id := i.U 1073f1d78cf7SLinJiawei e.io.l2_pf_store_only := io.l2_pf_store_only 107496b1e495SWilliam Wang e.io.req.valid := io.req.valid 107508b0bc30Shappy-lx e.io.wbq_block_miss_req := io.wbq_block_miss_req 107696b1e495SWilliam Wang e.io.primary_valid := io.req.valid && 107796b1e495SWilliam Wang !merge && 107896b1e495SWilliam Wang !reject && 107996b1e495SWilliam Wang !former_primary_ready && 108096b1e495SWilliam Wang e.io.primary_ready 1081e771db6cSWilliam Wang e.io.req.bits := io.req.bits.toMissReqWoStoreData() 10821f0e2dc7SJiawei Lin 1083ad3ba452Szhanglinjuan e.io.mem_grant.valid := false.B 1084ad3ba452Szhanglinjuan e.io.mem_grant.bits := DontCare 10851f0e2dc7SJiawei Lin when (io.mem_grant.bits.source === i.U) { 1086ad3ba452Szhanglinjuan e.io.mem_grant <> io.mem_grant 10871f0e2dc7SJiawei Lin } 10881f0e2dc7SJiawei Lin 10896b5c3d02Shappy-lx when(miss_req_pipe_reg.reg_valid() && miss_req_pipe_reg.mshr_id === i.U) { 10906b5c3d02Shappy-lx e.io.miss_req_pipe_reg := miss_req_pipe_reg 10916b5c3d02Shappy-lx }.otherwise { 10926b5c3d02Shappy-lx e.io.miss_req_pipe_reg := DontCare 10936b5c3d02Shappy-lx e.io.miss_req_pipe_reg.merge := false.B 10946b5c3d02Shappy-lx e.io.miss_req_pipe_reg.alloc := false.B 10956b5c3d02Shappy-lx } 10966b5c3d02Shappy-lx 10976b5c3d02Shappy-lx e.io.acquire_fired_by_pipe_reg := acquire_from_pipereg.fire 10986b5c3d02Shappy-lx 1099ad3ba452Szhanglinjuan e.io.main_pipe_resp := io.main_pipe_resp.valid && io.main_pipe_resp.bits.ack_miss_queue && io.main_pipe_resp.bits.miss_id === i.U 110073c515a4SCharlieLiu e.io.main_pipe_replay := io.mainpipe_info.s2_valid && io.mainpipe_info.s2_replay_to_mq && io.mainpipe_info.s2_miss_id === i.U 110173c515a4SCharlieLiu e.io.main_pipe_refill_resp := io.mainpipe_info.s3_valid && io.mainpipe_info.s3_refill_resp && io.mainpipe_info.s3_miss_id === i.U 11021f0e2dc7SJiawei Lin 11030d32f713Shappy-lx e.io.memSetPattenDetected := memSetPattenDetected 11040d32f713Shappy-lx e.io.nMaxPrefetchEntry := nMaxPrefetchEntry 11050d32f713Shappy-lx 1106f275998aSsfencevma e.io.main_pipe_req.ready := io.main_pipe_req.ready 1107ffd3154dSCharlieLiu 110808b0bc30Shappy-lx for (j <- 0 until reqNum) { 110908b0bc30Shappy-lx e.io.queryME(j).req.valid := io.queryMQ(j).req.valid 111008b0bc30Shappy-lx e.io.queryME(j).req.bits := io.queryMQ(j).req.bits.toMissReqWoStoreData() 111108b0bc30Shappy-lx } 111208b0bc30Shappy-lx 1113ffd3154dSCharlieLiu when(io.l2_hint.bits.sourceId === i.U) { 1114ffd3154dSCharlieLiu e.io.l2_hint <> io.l2_hint 1115ffd3154dSCharlieLiu } .otherwise { 1116ffd3154dSCharlieLiu e.io.l2_hint.valid := false.B 1117ffd3154dSCharlieLiu e.io.l2_hint.bits := DontCare 1118ffd3154dSCharlieLiu } 11191f0e2dc7SJiawei Lin } 11201f0e2dc7SJiawei Lin 1121dc4fac13SCharlieLiu cmo_unit.io.req <> io.cmo_req 1122dc4fac13SCharlieLiu io.cmo_resp <> cmo_unit.io.resp_to_lsq 1123dc4fac13SCharlieLiu when (io.mem_grant.valid && io.mem_grant.bits.opcode === TLMessages.CBOAck) { 1124dc4fac13SCharlieLiu cmo_unit.io.resp_chanD <> io.mem_grant 1125dc4fac13SCharlieLiu } .otherwise { 1126dc4fac13SCharlieLiu cmo_unit.io.resp_chanD.valid := false.B 1127dc4fac13SCharlieLiu cmo_unit.io.resp_chanD.bits := DontCare 1128dc4fac13SCharlieLiu } 1129dc4fac13SCharlieLiu 1130ad3ba452Szhanglinjuan io.req.ready := accept 1131ad3ba452Szhanglinjuan io.refill_to_ldq.valid := Cat(entries.map(_.io.refill_to_ldq.valid)).orR 1132ad3ba452Szhanglinjuan io.refill_to_ldq.bits := ParallelMux(entries.map(_.io.refill_to_ldq.valid) zip entries.map(_.io.refill_to_ldq.bits)) 11331f0e2dc7SJiawei Lin 113473c515a4SCharlieLiu io.refill_info.valid := VecInit(entries.zipWithIndex.map{ case(e,i) => e.io.refill_info.valid && io.mainpipe_info.s2_valid && io.mainpipe_info.s2_miss_id === i.U}).asUInt.orR 113573c515a4SCharlieLiu io.refill_info.bits := Mux1H(entries.zipWithIndex.map{ case(e,i) => (io.mainpipe_info.s2_miss_id === i.U) -> e.io.refill_info.bits }) 1136ffd3154dSCharlieLiu 11376b5c3d02Shappy-lx acquire_from_pipereg.valid := miss_req_pipe_reg.can_send_acquire(io.req.valid, io.req.bits) 11386b5c3d02Shappy-lx acquire_from_pipereg.bits := miss_req_pipe_reg.get_acquire(io.l2_pf_store_only) 11396b5c3d02Shappy-lx 11406b5c3d02Shappy-lx XSPerfAccumulate("acquire_fire_from_pipereg", acquire_from_pipereg.fire) 11416b5c3d02Shappy-lx XSPerfAccumulate("pipereg_valid", miss_req_pipe_reg.reg_valid()) 11426b5c3d02Shappy-lx 1143dc4fac13SCharlieLiu val acquire_sources = Seq(cmo_unit.io.req_chanA, acquire_from_pipereg) ++ entries.map(_.io.mem_acquire) 11446b5c3d02Shappy-lx TLArbiter.lowest(edge, io.mem_acquire, acquire_sources:_*) 1145ad3ba452Szhanglinjuan TLArbiter.lowest(edge, io.mem_finish, entries.map(_.io.mem_finish):_*) 1146ad3ba452Szhanglinjuan 1147f275998aSsfencevma // amo's main pipe req out 1148ffd3154dSCharlieLiu fastArbiter(entries.map(_.io.main_pipe_req), io.main_pipe_req, Some("main_pipe_req")) 11496005a7e2Shappy-lx 1150ad3ba452Szhanglinjuan io.probe_block := Cat(probe_block_vec).orR 1151ad3ba452Szhanglinjuan 11527ecd6591SCharlie Liu io.replace_block := io.replace_addr.valid && Cat(entries.map(e => e.io.req_addr.valid && e.io.req_addr.bits === io.replace_addr.bits) ++ Seq(miss_req_pipe_reg.block_match(io.replace_addr.bits))).orR 11531461d8f8SCharlieLiu 1154ad3ba452Szhanglinjuan io.full := ~Cat(entries.map(_.io.primary_ready)).andR 11551f0e2dc7SJiawei Lin 11560d32f713Shappy-lx // prefetch related 11570d32f713Shappy-lx io.prefetch_info.naive.late_miss_prefetch := io.req.valid && io.req.bits.isPrefetchRead && (miss_req_pipe_reg.matched(io.req.bits) || Cat(entries.map(_.io.matched)).orR) 11580d32f713Shappy-lx 11590d32f713Shappy-lx io.prefetch_info.fdp.late_miss_prefetch := (miss_req_pipe_reg.prefetch_late_en(io.req.bits.toMissReqWoStoreData(), io.req.valid) || Cat(entries.map(_.io.prefetch_info.late_prefetch)).orR) 1160ffd3154dSCharlieLiu io.prefetch_info.fdp.prefetch_monitor_cnt := io.main_pipe_req.fire 11610d32f713Shappy-lx io.prefetch_info.fdp.total_prefetch := alloc && io.req.valid && !io.req.bits.cancel && isFromL1Prefetch(io.req.bits.pf_source) 11620d32f713Shappy-lx 11632db9ec44SLinJiawei // L1MissTrace Chisel DB 11642db9ec44SLinJiawei val debug_miss_trace = Wire(new L1MissTrace) 11652db9ec44SLinJiawei debug_miss_trace.vaddr := io.req.bits.vaddr 11662db9ec44SLinJiawei debug_miss_trace.paddr := io.req.bits.addr 11672db9ec44SLinJiawei debug_miss_trace.source := io.req.bits.source 11682db9ec44SLinJiawei debug_miss_trace.pc := io.req.bits.pc 11692db9ec44SLinJiawei 1170c686adcdSYinan Xu val isWriteL1MissQMissTable = Constantin.createRecord(s"isWriteL1MissQMissTable${p(XSCoreParamsKey).HartId}") 1171c686adcdSYinan Xu val table = ChiselDB.createTable(s"L1MissQMissTrace_hart${p(XSCoreParamsKey).HartId}", new L1MissTrace) 1172da3bf434SMaxpicca-Li table.log(debug_miss_trace, isWriteL1MissQMissTable.orR && io.req.valid && !io.req.bits.cancel && alloc, "MissQueue", clock, reset) 11732db9ec44SLinJiawei 11742db9ec44SLinJiawei // Difftest 11751545277aSYinan Xu if (env.EnableDifftest) { 1176a0c65233SYinan Xu val difftest = DifftestModule(new DiffRefillEvent, dontCare = true) 11777d45a146SYinan Xu difftest.coreid := io.hartId 11787d45a146SYinan Xu difftest.index := 1.U 11797d45a146SYinan Xu difftest.valid := io.refill_to_ldq.valid && io.refill_to_ldq.bits.hasdata && io.refill_to_ldq.bits.refill_done 11807d45a146SYinan Xu difftest.addr := io.refill_to_ldq.bits.addr 11817d45a146SYinan Xu difftest.data := io.refill_to_ldq.bits.data_raw.asTypeOf(difftest.data) 1182935edac4STang Haojin difftest.idtfr := DontCare 11831f0e2dc7SJiawei Lin } 11841f0e2dc7SJiawei Lin 11852db9ec44SLinJiawei // Perf count 1186935edac4STang Haojin XSPerfAccumulate("miss_req", io.req.fire && !io.req.bits.cancel) 1187935edac4STang Haojin XSPerfAccumulate("miss_req_allocate", io.req.fire && !io.req.bits.cancel && alloc) 1188935edac4STang Haojin XSPerfAccumulate("miss_req_load_allocate", io.req.fire && !io.req.bits.cancel && alloc && io.req.bits.isFromLoad) 1189935edac4STang Haojin XSPerfAccumulate("miss_req_store_allocate", io.req.fire && !io.req.bits.cancel && alloc && io.req.bits.isFromStore) 1190935edac4STang Haojin XSPerfAccumulate("miss_req_amo_allocate", io.req.fire && !io.req.bits.cancel && alloc && io.req.bits.isFromAMO) 1191ffd3154dSCharlieLiu XSPerfAccumulate("miss_req_prefetch_allocate", io.req.fire && !io.req.bits.cancel && alloc && io.req.bits.isFromPrefetch) 1192935edac4STang Haojin XSPerfAccumulate("miss_req_merge_load", io.req.fire && !io.req.bits.cancel && merge && io.req.bits.isFromLoad) 1193d2b20d1aSTang Haojin XSPerfAccumulate("miss_req_reject_load", io.req.valid && !io.req.bits.cancel && reject && io.req.bits.isFromLoad) 11941f0e2dc7SJiawei Lin XSPerfAccumulate("probe_blocked_by_miss", io.probe_block) 1195935edac4STang Haojin XSPerfAccumulate("prefetch_primary_fire", io.req.fire && !io.req.bits.cancel && alloc && io.req.bits.isFromPrefetch) 1196935edac4STang Haojin XSPerfAccumulate("prefetch_secondary_fire", io.req.fire && !io.req.bits.cancel && merge && io.req.bits.isFromPrefetch) 11970d32f713Shappy-lx XSPerfAccumulate("memSetPattenDetected", memSetPattenDetected) 11981f0e2dc7SJiawei Lin val max_inflight = RegInit(0.U((log2Up(cfg.nMissEntries) + 1).W)) 1199ad3ba452Szhanglinjuan val num_valids = PopCount(~Cat(primary_ready_vec).asUInt) 12001f0e2dc7SJiawei Lin when (num_valids > max_inflight) { 12011f0e2dc7SJiawei Lin max_inflight := num_valids 12021f0e2dc7SJiawei Lin } 12031f0e2dc7SJiawei Lin // max inflight (average) = max_inflight_total / cycle cnt 12041f0e2dc7SJiawei Lin XSPerfAccumulate("max_inflight", max_inflight) 12051f0e2dc7SJiawei Lin QueuePerf(cfg.nMissEntries, num_valids, num_valids === cfg.nMissEntries.U) 12061f0e2dc7SJiawei Lin io.full := num_valids === cfg.nMissEntries.U 1207e836c770SZhaoyang You io.l1Miss := RegNext(Cat(entries.map(_.io.l1Miss)).orR) 12081f0e2dc7SJiawei Lin XSPerfHistogram("num_valids", num_valids, true.B, 0, cfg.nMissEntries, 1) 12091ca0e4f3SYinan Xu 1210d2b20d1aSTang Haojin XSPerfHistogram("L1DMLP_CPUData", PopCount(VecInit(entries.map(_.io.perf_pending_normal)).asUInt), true.B, 0, cfg.nMissEntries, 1) 1211d2b20d1aSTang Haojin XSPerfHistogram("L1DMLP_Prefetch", PopCount(VecInit(entries.map(_.io.perf_pending_prefetch)).asUInt), true.B, 0, cfg.nMissEntries, 1) 1212d2b20d1aSTang Haojin XSPerfHistogram("L1DMLP_Total", num_valids, true.B, 0, cfg.nMissEntries, 1) 1213d2b20d1aSTang Haojin 1214d2b20d1aSTang Haojin XSPerfAccumulate("miss_load_refill_latency", PopCount(entries.map(_.io.latency_monitor.load_miss_refilling))) 1215d2b20d1aSTang Haojin XSPerfAccumulate("miss_store_refill_latency", PopCount(entries.map(_.io.latency_monitor.store_miss_refilling))) 1216d2b20d1aSTang Haojin XSPerfAccumulate("miss_amo_refill_latency", PopCount(entries.map(_.io.latency_monitor.amo_miss_refilling))) 1217d2b20d1aSTang Haojin XSPerfAccumulate("miss_pf_refill_latency", PopCount(entries.map(_.io.latency_monitor.pf_miss_refilling))) 1218d2b20d1aSTang Haojin 1219d2b20d1aSTang Haojin val rob_head_miss_in_dcache = VecInit(entries.map(_.io.rob_head_query.resp)).asUInt.orR 1220d2b20d1aSTang Haojin 1221d2b20d1aSTang Haojin entries.foreach { 1222d2b20d1aSTang Haojin case e => { 122360ebee38STang Haojin e.io.rob_head_query.query_valid := io.debugTopDown.robHeadVaddr.valid 122460ebee38STang Haojin e.io.rob_head_query.vaddr := io.debugTopDown.robHeadVaddr.bits 1225d2b20d1aSTang Haojin } 1226d2b20d1aSTang Haojin } 1227d2b20d1aSTang Haojin 122860ebee38STang Haojin io.debugTopDown.robHeadMissInDCache := rob_head_miss_in_dcache 1229d2b20d1aSTang Haojin 1230b6d53cefSWilliam Wang val perfValidCount = RegNext(PopCount(entries.map(entry => (!entry.io.primary_ready)))) 1231cd365d4cSrvcoresjw val perfEvents = Seq( 1232935edac4STang Haojin ("dcache_missq_req ", io.req.fire), 1233b6d53cefSWilliam Wang ("dcache_missq_1_4_valid", (perfValidCount < (cfg.nMissEntries.U/4.U))), 1234b6d53cefSWilliam Wang ("dcache_missq_2_4_valid", (perfValidCount > (cfg.nMissEntries.U/4.U)) & (perfValidCount <= (cfg.nMissEntries.U/2.U))), 1235b6d53cefSWilliam Wang ("dcache_missq_3_4_valid", (perfValidCount > (cfg.nMissEntries.U/2.U)) & (perfValidCount <= (cfg.nMissEntries.U*3.U/4.U))), 1236b6d53cefSWilliam Wang ("dcache_missq_4_4_valid", (perfValidCount > (cfg.nMissEntries.U*3.U/4.U))), 1237cd365d4cSrvcoresjw ) 12381ca0e4f3SYinan Xu generatePerfEvent() 12391f0e2dc7SJiawei Lin} 1240