11d8f4dcbSJay/*************************************************************************************** 21d8f4dcbSJay* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 31d8f4dcbSJay* Copyright (c) 2020-2021 Peng Cheng Laboratory 41d8f4dcbSJay* 51d8f4dcbSJay* XiangShan is licensed under Mulan PSL v2. 61d8f4dcbSJay* You can use this software according to the terms and conditions of the Mulan PSL v2. 71d8f4dcbSJay* You may obtain a copy of Mulan PSL v2 at: 81d8f4dcbSJay* http://license.coscl.org.cn/MulanPSL2 91d8f4dcbSJay* 101d8f4dcbSJay* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 111d8f4dcbSJay* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 121d8f4dcbSJay* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 131d8f4dcbSJay* 141d8f4dcbSJay* See the Mulan PSL v2 for more details. 151d8f4dcbSJay***************************************************************************************/ 161d8f4dcbSJay 171d8f4dcbSJaypackage xiangshan.frontend.icache 181d8f4dcbSJay 191d8f4dcbSJayimport chisel3._ 201d8f4dcbSJayimport chisel3.util._ 21cf7d6b7aSMuziimport difftest._ 22cf7d6b7aSMuziimport freechips.rocketchip.tilelink._ 23cf7d6b7aSMuziimport org.chipsalliance.cde.config.Parameters 24cf7d6b7aSMuziimport utility._ 251d8f4dcbSJayimport xiangshan._ 261d8f4dcbSJay 27*415fcbe2Sxu_zhclass DeMultiplexerIO[T <: Data](gen: T, n: Int) extends Bundle { 28*415fcbe2Sxu_zh val in: DecoupledIO[T] = Flipped(DecoupledIO(gen)) 29*415fcbe2Sxu_zh val out: Vec[DecoupledIO[T]] = Vec(n, DecoupledIO(gen)) 30*415fcbe2Sxu_zh val chosen: UInt = Output(UInt(log2Ceil(n).W)) 31*415fcbe2Sxu_zh} 321d8f4dcbSJay 33*415fcbe2Sxu_zh/** Hardware module that is used to sequence 1 producer into n consumer. 34b92f8445Sssszwic * Priority is given to lower producer. 35b92f8445Sssszwic */ 36*415fcbe2Sxu_zhclass DeMultiplexer[T <: Data](val gen: T, val n: Int) extends Module { 37b92f8445Sssszwic require(n >= 2) 38*415fcbe2Sxu_zh val io: DeMultiplexerIO[T] = IO(new DeMultiplexerIO(gen, n)) 39b92f8445Sssszwic 40*415fcbe2Sxu_zh private val grant = false.B +: (1 until n).map(i => (0 until i).map(io.out(_).ready).reduce(_ || _)) 41*415fcbe2Sxu_zh (0 until n).foreach { i => 42b92f8445Sssszwic io.out(i).bits := io.in.bits 43b92f8445Sssszwic io.out(i).valid := !grant(i) && io.in.valid 44b92f8445Sssszwic } 45b92f8445Sssszwic 46b92f8445Sssszwic io.in.ready := grant.last || io.out.last.ready 47b92f8445Sssszwic io.chosen := PriorityEncoder(VecInit(io.out.map(_.ready))) 481d8f4dcbSJay} 491d8f4dcbSJay 50*415fcbe2Sxu_zhclass MuxBundleIO[T <: Data](gen: T, n: Int) extends Bundle { 51*415fcbe2Sxu_zh val sel: UInt = Input(UInt(log2Ceil(n).W)) 52*415fcbe2Sxu_zh val in: Vec[DecoupledIO[T]] = Flipped(Vec(n, DecoupledIO(gen))) 53*415fcbe2Sxu_zh val out: DecoupledIO[T] = DecoupledIO(gen) 54*415fcbe2Sxu_zh} 55*415fcbe2Sxu_zh 56cf7d6b7aSMuziclass MuxBundle[T <: Data](val gen: T, val n: Int) extends Module { 57b92f8445Sssszwic require(n >= 2) 58*415fcbe2Sxu_zh val io: MuxBundleIO[T] = IO(new MuxBundleIO[T](gen, n)) 59b92f8445Sssszwic 60b92f8445Sssszwic io.in <> DontCare 61b92f8445Sssszwic io.out <> DontCare 62*415fcbe2Sxu_zh (0 until n).foreach { i => 63b92f8445Sssszwic when(io.sel === i.U) { 64b92f8445Sssszwic io.out <> io.in(i) 65b92f8445Sssszwic } 66b92f8445Sssszwic io.in(i).ready := (io.sel === i.U) && io.out.ready 67b92f8445Sssszwic } 68b92f8445Sssszwic} 69b92f8445Sssszwic 70b92f8445Sssszwicclass ICacheMissReq(implicit p: Parameters) extends ICacheBundle { 71*415fcbe2Sxu_zh val blkPaddr: UInt = UInt((PAddrBits - blockOffBits).W) 72*415fcbe2Sxu_zh val vSetIdx: UInt = UInt(idxBits.W) 73b92f8445Sssszwic} 74b92f8445Sssszwic 75b92f8445Sssszwicclass ICacheMissResp(implicit p: Parameters) extends ICacheBundle { 76*415fcbe2Sxu_zh val blkPaddr: UInt = UInt((PAddrBits - blockOffBits).W) 77*415fcbe2Sxu_zh val vSetIdx: UInt = UInt(idxBits.W) 78*415fcbe2Sxu_zh val waymask: UInt = UInt(nWays.W) 79*415fcbe2Sxu_zh val data: UInt = UInt(blockBits.W) 80*415fcbe2Sxu_zh val corrupt: Bool = Bool() 811d8f4dcbSJay} 821d8f4dcbSJay 83b92f8445Sssszwicclass LookUpMSHR(implicit p: Parameters) extends ICacheBundle { 84*415fcbe2Sxu_zh val info: Valid[ICacheMissReq] = ValidIO(new ICacheMissReq) 85*415fcbe2Sxu_zh val hit: Bool = Input(Bool()) 861d8f4dcbSJay} 871d8f4dcbSJay 88b92f8445Sssszwicclass MSHRResp(implicit p: Parameters) extends ICacheBundle { 89*415fcbe2Sxu_zh val blkPaddr: UInt = UInt((PAddrBits - blockOffBits).W) 90*415fcbe2Sxu_zh val vSetIdx: UInt = UInt(idxBits.W) 91*415fcbe2Sxu_zh val way: UInt = UInt(wayBits.W) 92b92f8445Sssszwic} 93b92f8445Sssszwic 94b92f8445Sssszwicclass MSHRAcquire(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle { 95*415fcbe2Sxu_zh val acquire: TLBundleA = new TLBundleA(edge.bundle) 96*415fcbe2Sxu_zh val vSetIdx: UInt = UInt(idxBits.W) 97b92f8445Sssszwic} 98b92f8445Sssszwic 99*415fcbe2Sxu_zhclass ICacheMSHRIO(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle { 100*415fcbe2Sxu_zh val fencei: Bool = Input(Bool()) 101*415fcbe2Sxu_zh val flush: Bool = Input(Bool()) 102*415fcbe2Sxu_zh val invalid: Bool = Input(Bool()) 103*415fcbe2Sxu_zh val req: DecoupledIO[ICacheMissReq] = Flipped(DecoupledIO(new ICacheMissReq)) 104*415fcbe2Sxu_zh val acquire: DecoupledIO[MSHRAcquire] = DecoupledIO(new MSHRAcquire(edge)) 105*415fcbe2Sxu_zh val lookUps: Vec[LookUpMSHR] = Flipped(Vec(2, new LookUpMSHR)) 106*415fcbe2Sxu_zh val resp: Valid[MSHRResp] = ValidIO(new MSHRResp) 107*415fcbe2Sxu_zh val victimWay: UInt = Input(UInt(wayBits.W)) 108*415fcbe2Sxu_zh} 1091d8f4dcbSJay 110*415fcbe2Sxu_zhclass ICacheMSHR(edge: TLEdgeOut, isFetch: Boolean, ID: Int)(implicit p: Parameters) extends ICacheModule { 111*415fcbe2Sxu_zh val io: ICacheMSHRIO = IO(new ICacheMSHRIO(edge)) 112*415fcbe2Sxu_zh 113*415fcbe2Sxu_zh private val valid = RegInit(Bool(), false.B) 114*415fcbe2Sxu_zh // this MSHR doesn't respond to fetch and sram 115*415fcbe2Sxu_zh private val flush = RegInit(Bool(), false.B) 116*415fcbe2Sxu_zh private val fencei = RegInit(Bool(), false.B) 117b92f8445Sssszwic // this MSHR has been issued 118*415fcbe2Sxu_zh private val issue = RegInit(Bool(), false.B) 1191d8f4dcbSJay 120*415fcbe2Sxu_zh private val blkPaddr = RegInit(UInt((PAddrBits - blockOffBits).W), 0.U) 121*415fcbe2Sxu_zh private val vSetIdx = RegInit(UInt(idxBits.W), 0.U) 122*415fcbe2Sxu_zh private val way = RegInit(UInt(wayBits.W), 0.U) 1231d8f4dcbSJay 124b92f8445Sssszwic // look up and return result at the same cycle 125*415fcbe2Sxu_zh private val hits = io.lookUps.map { lookup => 126cf7d6b7aSMuzi valid && !fencei && !flush && (lookup.info.bits.vSetIdx === vSetIdx) && 127cf7d6b7aSMuzi (lookup.info.bits.blkPaddr === blkPaddr) 128*415fcbe2Sxu_zh } 129b92f8445Sssszwic // Decoupling valid and bits 130cf7d6b7aSMuzi (0 until 2).foreach(i => io.lookUps(i).hit := hits(i)) 1311d8f4dcbSJay 132b92f8445Sssszwic // disable wake up when hit MSHR (fencei is low) 133b92f8445Sssszwic // when(hit) { 134b92f8445Sssszwic // flush := false.B 135b92f8445Sssszwic // } 1362a6078bfSguohongyu 137b92f8445Sssszwic // invalid when the req hasn't been issued 138b92f8445Sssszwic when(io.fencei || io.flush) { 139b92f8445Sssszwic fencei := true.B 140b92f8445Sssszwic flush := true.B 141b92f8445Sssszwic when(!issue) { 142b92f8445Sssszwic valid := false.B 143b92f8445Sssszwic } 144b92f8445Sssszwic } 1451d8f4dcbSJay 146b92f8445Sssszwic // receive request and register 147b92f8445Sssszwic io.req.ready := !valid && !io.flush && !io.fencei 148935edac4STang Haojin when(io.req.fire) { 149b92f8445Sssszwic valid := true.B 150b92f8445Sssszwic flush := false.B 151b92f8445Sssszwic issue := false.B 152b92f8445Sssszwic fencei := false.B 153b92f8445Sssszwic blkPaddr := io.req.bits.blkPaddr 154b92f8445Sssszwic vSetIdx := io.req.bits.vSetIdx 1551d8f4dcbSJay } 1561d8f4dcbSJay 157b92f8445Sssszwic // send request to L2 158b92f8445Sssszwic io.acquire.valid := valid && !issue && !io.flush && !io.fencei 159*415fcbe2Sxu_zh private val getBlock = edge.Get( 160b92f8445Sssszwic fromSource = ID.U, 161b92f8445Sssszwic toAddress = Cat(blkPaddr, 0.U(blockOffBits.W)), 162cf7d6b7aSMuzi lgSize = log2Up(cacheParams.blockBytes).U 16338160951Sguohongyu )._2 164b92f8445Sssszwic io.acquire.bits.acquire := getBlock 165b92f8445Sssszwic io.acquire.bits.acquire.user.lift(ReqSourceKey).foreach(_ := MemReqSource.CPUInst.id.U) 166b92f8445Sssszwic io.acquire.bits.vSetIdx := vSetIdx 16738160951Sguohongyu 168b92f8445Sssszwic // get victim way when acquire fire 169b92f8445Sssszwic when(io.acquire.fire) { 170b92f8445Sssszwic issue := true.B 171*415fcbe2Sxu_zh way := io.victimWay 172b92f8445Sssszwic } 1731d8f4dcbSJay 174b92f8445Sssszwic // invalid request when grant finish 175b92f8445Sssszwic when(io.invalid) { 176b92f8445Sssszwic valid := false.B 177b92f8445Sssszwic } 1782a25dbb4SJay 179b92f8445Sssszwic // offer the information other than data for write sram and response fetch 180b92f8445Sssszwic io.resp.valid := valid && (!flush && !fencei) 181b92f8445Sssszwic io.resp.bits.blkPaddr := blkPaddr 182b92f8445Sssszwic io.resp.bits.vSetIdx := vSetIdx 183*415fcbe2Sxu_zh io.resp.bits.way := way 184b92f8445Sssszwic} 185131aa97cSssszwic 186*415fcbe2Sxu_zhclass ICacheMissUnitIO(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle { 187b92f8445Sssszwic // difftest 188*415fcbe2Sxu_zh val hartId: Bool = Input(Bool()) 189b92f8445Sssszwic // control 190*415fcbe2Sxu_zh val fencei: Bool = Input(Bool()) 191*415fcbe2Sxu_zh val flush: Bool = Input(Bool()) 192b92f8445Sssszwic // fetch 193*415fcbe2Sxu_zh val fetch_req: DecoupledIO[ICacheMissReq] = Flipped(DecoupledIO(new ICacheMissReq)) 194*415fcbe2Sxu_zh val fetch_resp: Valid[ICacheMissResp] = ValidIO(new ICacheMissResp) 195b92f8445Sssszwic // prefetch 196*415fcbe2Sxu_zh val prefetch_req: DecoupledIO[ICacheMissReq] = Flipped(DecoupledIO(new ICacheMissReq)) 197b92f8445Sssszwic // SRAM Write Req 198*415fcbe2Sxu_zh val meta_write: DecoupledIO[ICacheMetaWriteBundle] = DecoupledIO(new ICacheMetaWriteBundle) 199*415fcbe2Sxu_zh val data_write: DecoupledIO[ICacheDataWriteBundle] = DecoupledIO(new ICacheDataWriteBundle) 200b92f8445Sssszwic // get victim from replacer 201*415fcbe2Sxu_zh val victim: ReplacerVictim = new ReplacerVictim 202b92f8445Sssszwic // Tilelink 203*415fcbe2Sxu_zh val mem_acquire: DecoupledIO[TLBundleA] = DecoupledIO(new TLBundleA(edge.bundle)) 204*415fcbe2Sxu_zh val mem_grant: DecoupledIO[TLBundleD] = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 2051d8f4dcbSJay} 2061d8f4dcbSJay 207*415fcbe2Sxu_zhclass ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheModule { 208*415fcbe2Sxu_zh val io: ICacheMissUnitIO = IO(new ICacheMissUnitIO(edge)) 2091d8f4dcbSJay 210b92f8445Sssszwic /** 211b92f8445Sssszwic ****************************************************************************** 212b92f8445Sssszwic * fetch have higher priority 213b92f8445Sssszwic * fetch MSHR: lower index have a higher priority 214b92f8445Sssszwic * prefetch MSHR: the prefetchMSHRs earlier have a higher priority 215b92f8445Sssszwic * --------- -------------- ----------- 216b92f8445Sssszwic * ---fetch reg--->| Demux |-----> | fetch MSHR |------>| Arbiter |---acquire---> 217b92f8445Sssszwic * --------- -------------- ----------- 218b92f8445Sssszwic * | fetch MSHR | ^ 219b92f8445Sssszwic * -------------- | 220b92f8445Sssszwic * | 221b92f8445Sssszwic * ----------------- | 222b92f8445Sssszwic * | prefetch MSHR | | 223b92f8445Sssszwic * --------- ----------------- ----------- 224b92f8445Sssszwic * ---fetch reg--->| Demux |----> | prefetch MSHR |---->| Arbiter | 225b92f8445Sssszwic * --------- ----------------- ----------- 226b92f8445Sssszwic * | ....... | 227b92f8445Sssszwic * ----------------- 228b92f8445Sssszwic ****************************************************************************** 229b92f8445Sssszwic */ 2301d8f4dcbSJay 231*415fcbe2Sxu_zh private val fetchDemux = Module(new DeMultiplexer(new ICacheMissReq, nFetchMshr)) 232*415fcbe2Sxu_zh private val prefetchDemux = Module(new DeMultiplexer(new ICacheMissReq, nPrefetchMshr)) 233*415fcbe2Sxu_zh private val prefetchArb = Module(new MuxBundle(new MSHRAcquire(edge), nPrefetchMshr)) 234*415fcbe2Sxu_zh private val acquireArb = Module(new Arbiter(new MSHRAcquire(edge), nFetchMshr + 1)) 235cb6e5d3cSssszwic 236b92f8445Sssszwic // To avoid duplicate request reception. 237*415fcbe2Sxu_zh private val fetchHit = Wire(Bool()) 238*415fcbe2Sxu_zh private val prefetchHit = Wire(Bool()) 239b92f8445Sssszwic fetchDemux.io.in <> io.fetch_req 240b92f8445Sssszwic fetchDemux.io.in.valid := io.fetch_req.valid && !fetchHit 241b92f8445Sssszwic io.fetch_req.ready := fetchDemux.io.in.ready || fetchHit 242b92f8445Sssszwic prefetchDemux.io.in <> io.prefetch_req 243b92f8445Sssszwic prefetchDemux.io.in.valid := io.prefetch_req.valid && !prefetchHit 244b92f8445Sssszwic io.prefetch_req.ready := prefetchDemux.io.in.ready || prefetchHit 245b92f8445Sssszwic acquireArb.io.in.last <> prefetchArb.io.out 2461d8f4dcbSJay 247b92f8445Sssszwic // mem_acquire connect 248b92f8445Sssszwic io.mem_acquire.valid := acquireArb.io.out.valid 249b92f8445Sssszwic io.mem_acquire.bits := acquireArb.io.out.bits.acquire 250b92f8445Sssszwic acquireArb.io.out.ready := io.mem_acquire.ready 2511d8f4dcbSJay 252*415fcbe2Sxu_zh private val fetchMSHRs = (0 until nFetchMshr).map { i => 253b92f8445Sssszwic val mshr = Module(new ICacheMSHR(edge, true, i)) 254b92f8445Sssszwic mshr.io.flush := false.B 255b92f8445Sssszwic mshr.io.fencei := io.fencei 256b92f8445Sssszwic mshr.io.req <> fetchDemux.io.out(i) 257b92f8445Sssszwic mshr.io.lookUps(0).info.valid := io.fetch_req.valid 258b92f8445Sssszwic mshr.io.lookUps(0).info.bits := io.fetch_req.bits 259b92f8445Sssszwic mshr.io.lookUps(1).info.valid := io.prefetch_req.valid 260b92f8445Sssszwic mshr.io.lookUps(1).info.bits := io.prefetch_req.bits 261b92f8445Sssszwic mshr.io.victimWay := io.victim.way 262b92f8445Sssszwic acquireArb.io.in(i) <> mshr.io.acquire 263b92f8445Sssszwic mshr 2641d8f4dcbSJay } 2651d8f4dcbSJay 266*415fcbe2Sxu_zh private val prefetchMSHRs = (0 until nPrefetchMshr).map { i => 267b92f8445Sssszwic val mshr = Module(new ICacheMSHR(edge, false, nFetchMshr + i)) 268b92f8445Sssszwic mshr.io.flush := io.flush 269b92f8445Sssszwic mshr.io.fencei := io.fencei 270b92f8445Sssszwic mshr.io.req <> prefetchDemux.io.out(i) 271b92f8445Sssszwic mshr.io.lookUps(0).info.valid := io.fetch_req.valid 272b92f8445Sssszwic mshr.io.lookUps(0).info.bits := io.fetch_req.bits 273b92f8445Sssszwic mshr.io.lookUps(1).info.valid := io.prefetch_req.valid 274b92f8445Sssszwic mshr.io.lookUps(1).info.bits := io.prefetch_req.bits 275b92f8445Sssszwic mshr.io.victimWay := io.victim.way 276b92f8445Sssszwic prefetchArb.io.in(i) <> mshr.io.acquire 277b92f8445Sssszwic mshr 2787052722fSJay } 2797052722fSJay 28058c354d0Sssszwic /** 28158c354d0Sssszwic ****************************************************************************** 282b92f8445Sssszwic * MSHR look up 283b92f8445Sssszwic * - look up all mshr 28458c354d0Sssszwic ****************************************************************************** 28558c354d0Sssszwic */ 286*415fcbe2Sxu_zh private val allMSHRs = fetchMSHRs ++ prefetchMSHRs 287*415fcbe2Sxu_zh private val prefetchHitFetchReq = (io.prefetch_req.bits.blkPaddr === io.fetch_req.bits.blkPaddr) && 288b92f8445Sssszwic (io.prefetch_req.bits.vSetIdx === io.fetch_req.bits.vSetIdx) && 289b92f8445Sssszwic io.fetch_req.valid 290b92f8445Sssszwic fetchHit := allMSHRs.map(mshr => mshr.io.lookUps(0).hit).reduce(_ || _) 291b92f8445Sssszwic prefetchHit := allMSHRs.map(mshr => mshr.io.lookUps(1).hit).reduce(_ || _) || prefetchHitFetchReq 29258c354d0Sssszwic 293b92f8445Sssszwic /** 294b92f8445Sssszwic ****************************************************************************** 295b92f8445Sssszwic * prefetchMSHRs priority 296b92f8445Sssszwic * - The requests that enter the prefetchMSHRs earlier have a higher priority in issuing. 297*415fcbe2Sxu_zh * - The order of enqueuing is recorded in FIFO when request enters MSHRs. 298b92f8445Sssszwic * - The requests are dispatched in the order they are recorded in FIFO. 299b92f8445Sssszwic ****************************************************************************** 300b92f8445Sssszwic */ 301b92f8445Sssszwic // When the FIFO is full, enqueue and dequeue operations do not occur at the same cycle. 302b92f8445Sssszwic // So the depth of the FIFO is set to match the number of MSHRs. 303b92f8445Sssszwic // val priorityFIFO = Module(new Queue(UInt(log2Ceil(nPrefetchMshr).W), nPrefetchMshr, hasFlush=true)) 304*415fcbe2Sxu_zh private val priorityFIFO = Module(new FIFOReg(UInt(log2Ceil(nPrefetchMshr).W), nPrefetchMshr, hasFlush = true)) 305b92f8445Sssszwic priorityFIFO.io.flush.get := io.flush || io.fencei 306b92f8445Sssszwic priorityFIFO.io.enq.valid := prefetchDemux.io.in.fire 307b92f8445Sssszwic priorityFIFO.io.enq.bits := prefetchDemux.io.chosen 308b92f8445Sssszwic priorityFIFO.io.deq.ready := prefetchArb.io.out.fire 309b92f8445Sssszwic prefetchArb.io.sel := priorityFIFO.io.deq.bits 310cf7d6b7aSMuzi assert( 311cf7d6b7aSMuzi !(priorityFIFO.io.enq.fire ^ prefetchDemux.io.in.fire), 312cf7d6b7aSMuzi "priorityFIFO.io.enq and io.prefetch_req must fire at the same cycle" 313cf7d6b7aSMuzi ) 314cf7d6b7aSMuzi assert( 315cf7d6b7aSMuzi !(priorityFIFO.io.deq.fire ^ prefetchArb.io.out.fire), 316cf7d6b7aSMuzi "priorityFIFO.io.deq and prefetchArb.io.out must fire at the same cycle" 317cf7d6b7aSMuzi ) 3187052722fSJay 319b92f8445Sssszwic /** 320b92f8445Sssszwic ****************************************************************************** 321b92f8445Sssszwic * Tilelink D channel (grant) 322b92f8445Sssszwic ****************************************************************************** 323b92f8445Sssszwic */ 324b92f8445Sssszwic // cacheline register 325*415fcbe2Sxu_zh private val readBeatCnt = RegInit(UInt(log2Up(refillCycles).W), 0.U) 326*415fcbe2Sxu_zh private val respDataReg = RegInit(VecInit(Seq.fill(refillCycles)(0.U(beatBits.W)))) 3271d8f4dcbSJay 328*415fcbe2Sxu_zh private val wait_last = readBeatCnt === (refillCycles - 1).U 329b92f8445Sssszwic when(io.mem_grant.fire && edge.hasData(io.mem_grant.bits)) { 330b92f8445Sssszwic respDataReg(readBeatCnt) := io.mem_grant.bits.data 33133a531f0Sxu_zh readBeatCnt := Mux(wait_last, 0.U, readBeatCnt + 1.U) 332b92f8445Sssszwic } 333b92f8445Sssszwic 334*415fcbe2Sxu_zh // last transition finish or corrupt 335*415fcbe2Sxu_zh private val last_fire = io.mem_grant.fire && edge.hasData(io.mem_grant.bits) && wait_last 336b92f8445Sssszwic 337*415fcbe2Sxu_zh private val (_, _, refill_done, _) = edge.addr_inc(io.mem_grant) 338b92f8445Sssszwic assert(!(refill_done ^ last_fire), "refill not done!") 339b92f8445Sssszwic io.mem_grant.ready := true.B 340b92f8445Sssszwic 341*415fcbe2Sxu_zh private val last_fire_r = RegNext(last_fire) 342*415fcbe2Sxu_zh private val id_r = RegNext(io.mem_grant.bits.source) 34333a531f0Sxu_zh 34433a531f0Sxu_zh // if any beat is corrupt, the whole response (to mainPipe/metaArray/dataArray) is corrupt 345*415fcbe2Sxu_zh private val corrupt_r = RegInit(false.B) 34633a531f0Sxu_zh when(io.mem_grant.fire && edge.hasData(io.mem_grant.bits) && io.mem_grant.bits.corrupt) { 34733a531f0Sxu_zh corrupt_r := true.B 34833a531f0Sxu_zh }.elsewhen(io.fetch_resp.fire) { 34933a531f0Sxu_zh corrupt_r := false.B 35033a531f0Sxu_zh } 351b92f8445Sssszwic 352b92f8445Sssszwic /** 353b92f8445Sssszwic ****************************************************************************** 354b92f8445Sssszwic * invalid mshr when finish transition 355b92f8445Sssszwic ****************************************************************************** 356b92f8445Sssszwic */ 357cf7d6b7aSMuzi (0 until (nFetchMshr + nPrefetchMshr)).foreach(i => allMSHRs(i).io.invalid := last_fire_r && (id_r === i.U)) 358b92f8445Sssszwic 359b92f8445Sssszwic /** 360b92f8445Sssszwic ****************************************************************************** 361b92f8445Sssszwic * response fetch and write SRAM 362b92f8445Sssszwic ****************************************************************************** 363b92f8445Sssszwic */ 364b92f8445Sssszwic // get request information from MSHRs 365*415fcbe2Sxu_zh private val allMSHRs_resp = VecInit(allMSHRs.map(mshr => mshr.io.resp)) 366*415fcbe2Sxu_zh private val mshr_resp = allMSHRs_resp(id_r) 367b92f8445Sssszwic 368b92f8445Sssszwic // get waymask from replacer when acquire fire 3697a63335aSxu_zh io.victim.vSetIdx.valid := acquireArb.io.out.fire 370b92f8445Sssszwic io.victim.vSetIdx.bits := acquireArb.io.out.bits.vSetIdx 371*415fcbe2Sxu_zh private val waymask = UIntToOH(mshr_resp.bits.way) 372adf97c94Sxu_zh // NOTE: when flush/fencei, missUnit will still send response to mainPipe/prefetchPipe 373adf97c94Sxu_zh // this is intentional to fix timing (io.flush -> mainPipe/prefetchPipe s2_miss -> s2_ready -> ftq ready) 374adf97c94Sxu_zh // unnecessary response will be dropped by mainPipe/prefetchPipe/wayLookup since their sx_valid is set to false 375*415fcbe2Sxu_zh private val fetch_resp_valid = mshr_resp.valid && last_fire_r 376adf97c94Sxu_zh // NOTE: but we should not write meta/dataArray when flush/fencei 377*415fcbe2Sxu_zh private val write_sram_valid = fetch_resp_valid && !corrupt_r && !io.flush && !io.fencei 378b92f8445Sssszwic 379b92f8445Sssszwic // write SRAM 380cf7d6b7aSMuzi io.meta_write.bits.generate( 381cf7d6b7aSMuzi tag = getPhyTagFromBlk(mshr_resp.bits.blkPaddr), 382b92f8445Sssszwic idx = mshr_resp.bits.vSetIdx, 383b92f8445Sssszwic waymask = waymask, 384cf7d6b7aSMuzi bankIdx = mshr_resp.bits.vSetIdx(0) 385cf7d6b7aSMuzi ) 386cf7d6b7aSMuzi io.data_write.bits.generate( 387cf7d6b7aSMuzi data = respDataReg.asUInt, 388b92f8445Sssszwic idx = mshr_resp.bits.vSetIdx, 389b92f8445Sssszwic waymask = waymask, 390cf7d6b7aSMuzi bankIdx = mshr_resp.bits.vSetIdx(0) 391cf7d6b7aSMuzi ) 392b92f8445Sssszwic 393b92f8445Sssszwic io.meta_write.valid := write_sram_valid 394b92f8445Sssszwic io.data_write.valid := write_sram_valid 395b92f8445Sssszwic 396b92f8445Sssszwic // response fetch 397b92f8445Sssszwic io.fetch_resp.valid := fetch_resp_valid 398b92f8445Sssszwic io.fetch_resp.bits.blkPaddr := mshr_resp.bits.blkPaddr 399b92f8445Sssszwic io.fetch_resp.bits.vSetIdx := mshr_resp.bits.vSetIdx 400b92f8445Sssszwic io.fetch_resp.bits.waymask := waymask 401b92f8445Sssszwic io.fetch_resp.bits.data := respDataReg.asUInt 402b92f8445Sssszwic io.fetch_resp.bits.corrupt := corrupt_r 403b92f8445Sssszwic 404b92f8445Sssszwic /** 405b92f8445Sssszwic ****************************************************************************** 406b92f8445Sssszwic * performance counter 407b92f8445Sssszwic ****************************************************************************** 408b92f8445Sssszwic */ 409b92f8445Sssszwic // Duplicate requests will be excluded. 410b92f8445Sssszwic XSPerfAccumulate("enq_fetch_req", fetchDemux.io.in.fire) 411b92f8445Sssszwic XSPerfAccumulate("enq_prefetch_req", prefetchDemux.io.in.fire) 412b92f8445Sssszwic 413b92f8445Sssszwic /** 414b92f8445Sssszwic ****************************************************************************** 415b92f8445Sssszwic * ChiselDB: record ICache SRAM write log 416b92f8445Sssszwic ****************************************************************************** 417b92f8445Sssszwic */ 418*415fcbe2Sxu_zh private class ICacheSRAMDB(implicit p: Parameters) extends ICacheBundle { 419*415fcbe2Sxu_zh val blkPaddr: UInt = UInt((PAddrBits - blockOffBits).W) 420*415fcbe2Sxu_zh val vSetIdx: UInt = UInt(idxBits.W) 421*415fcbe2Sxu_zh val waymask: UInt = UInt(wayBits.W) 422b92f8445Sssszwic } 423b92f8445Sssszwic 424*415fcbe2Sxu_zh private val isWriteICacheSRAMTable = 425cf7d6b7aSMuzi WireInit(Constantin.createRecord("isWriteICacheSRAMTable" + p(XSCoreParamsKey).HartId.toString)) 426*415fcbe2Sxu_zh private val ICacheSRAMTable = 427*415fcbe2Sxu_zh ChiselDB.createTable("ICacheSRAMTable" + p(XSCoreParamsKey).HartId.toString, new ICacheSRAMDB) 428b92f8445Sssszwic 429*415fcbe2Sxu_zh private val ICacheSRAMDBDumpData = Wire(new ICacheSRAMDB) 430b92f8445Sssszwic ICacheSRAMDBDumpData.blkPaddr := mshr_resp.bits.blkPaddr 431b92f8445Sssszwic ICacheSRAMDBDumpData.vSetIdx := mshr_resp.bits.vSetIdx 432b92f8445Sssszwic ICacheSRAMDBDumpData.waymask := OHToUInt(waymask) 433b92f8445Sssszwic ICacheSRAMTable.log( 434b92f8445Sssszwic data = ICacheSRAMDBDumpData, 435b92f8445Sssszwic en = write_sram_valid, 436b92f8445Sssszwic clock = clock, 437b92f8445Sssszwic reset = reset 438b92f8445Sssszwic ) 439b92f8445Sssszwic 440b92f8445Sssszwic /** 441b92f8445Sssszwic ****************************************************************************** 442b92f8445Sssszwic * Difftest 443b92f8445Sssszwic ****************************************************************************** 444b92f8445Sssszwic */ 445afa866b1Sguohongyu if (env.EnableDifftest) { 446a0c65233SYinan Xu val difftest = DifftestModule(new DiffRefillEvent, dontCare = true) 4477d45a146SYinan Xu difftest.coreid := io.hartId 4487d45a146SYinan Xu difftest.index := 0.U 449b92f8445Sssszwic difftest.valid := write_sram_valid 450b92f8445Sssszwic difftest.addr := Cat(mshr_resp.bits.blkPaddr, 0.U(blockOffBits.W)) 451b92f8445Sssszwic difftest.data := respDataReg.asTypeOf(difftest.data) 452935edac4STang Haojin difftest.idtfr := DontCare 45341cb8b61SJenius } 4541d8f4dcbSJay} 455