11d8f4dcbSJay/*************************************************************************************** 26c106319Sxu_zh* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 36c106319Sxu_zh* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences 41d8f4dcbSJay* Copyright (c) 2020-2021 Peng Cheng Laboratory 51d8f4dcbSJay* 61d8f4dcbSJay* XiangShan is licensed under Mulan PSL v2. 71d8f4dcbSJay* You can use this software according to the terms and conditions of the Mulan PSL v2. 81d8f4dcbSJay* You may obtain a copy of Mulan PSL v2 at: 91d8f4dcbSJay* http://license.coscl.org.cn/MulanPSL2 101d8f4dcbSJay* 111d8f4dcbSJay* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 121d8f4dcbSJay* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 131d8f4dcbSJay* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 141d8f4dcbSJay* 151d8f4dcbSJay* See the Mulan PSL v2 for more details. 161d8f4dcbSJay***************************************************************************************/ 171d8f4dcbSJay 181d8f4dcbSJaypackage xiangshan.frontend.icache 191d8f4dcbSJay 201d8f4dcbSJayimport chisel3._ 211d8f4dcbSJayimport chisel3.util._ 22cf7d6b7aSMuziimport difftest._ 23cf7d6b7aSMuziimport freechips.rocketchip.tilelink._ 24cf7d6b7aSMuziimport org.chipsalliance.cde.config.Parameters 25cf7d6b7aSMuziimport utility._ 261d8f4dcbSJayimport xiangshan._ 271d8f4dcbSJay 28415fcbe2Sxu_zhclass DeMultiplexerIO[T <: Data](gen: T, n: Int) extends Bundle { 29415fcbe2Sxu_zh val in: DecoupledIO[T] = Flipped(DecoupledIO(gen)) 30415fcbe2Sxu_zh val out: Vec[DecoupledIO[T]] = Vec(n, DecoupledIO(gen)) 31415fcbe2Sxu_zh val chosen: UInt = Output(UInt(log2Ceil(n).W)) 32415fcbe2Sxu_zh} 331d8f4dcbSJay 34415fcbe2Sxu_zh/** Hardware module that is used to sequence 1 producer into n consumer. 35b92f8445Sssszwic * Priority is given to lower producer. 36b92f8445Sssszwic */ 37415fcbe2Sxu_zhclass DeMultiplexer[T <: Data](val gen: T, val n: Int) extends Module { 38b92f8445Sssszwic require(n >= 2) 39415fcbe2Sxu_zh val io: DeMultiplexerIO[T] = IO(new DeMultiplexerIO(gen, n)) 40b92f8445Sssszwic 41415fcbe2Sxu_zh private val grant = false.B +: (1 until n).map(i => (0 until i).map(io.out(_).ready).reduce(_ || _)) 42415fcbe2Sxu_zh (0 until n).foreach { i => 43b92f8445Sssszwic io.out(i).bits := io.in.bits 44b92f8445Sssszwic io.out(i).valid := !grant(i) && io.in.valid 45b92f8445Sssszwic } 46b92f8445Sssszwic 47b92f8445Sssszwic io.in.ready := grant.last || io.out.last.ready 48b92f8445Sssszwic io.chosen := PriorityEncoder(VecInit(io.out.map(_.ready))) 491d8f4dcbSJay} 501d8f4dcbSJay 51415fcbe2Sxu_zhclass MuxBundleIO[T <: Data](gen: T, n: Int) extends Bundle { 52415fcbe2Sxu_zh val sel: UInt = Input(UInt(log2Ceil(n).W)) 53415fcbe2Sxu_zh val in: Vec[DecoupledIO[T]] = Flipped(Vec(n, DecoupledIO(gen))) 54415fcbe2Sxu_zh val out: DecoupledIO[T] = DecoupledIO(gen) 55415fcbe2Sxu_zh} 56415fcbe2Sxu_zh 57cf7d6b7aSMuziclass MuxBundle[T <: Data](val gen: T, val n: Int) extends Module { 58b92f8445Sssszwic require(n >= 2) 59415fcbe2Sxu_zh val io: MuxBundleIO[T] = IO(new MuxBundleIO[T](gen, n)) 60b92f8445Sssszwic 61b92f8445Sssszwic io.in <> DontCare 62b92f8445Sssszwic io.out <> DontCare 63415fcbe2Sxu_zh (0 until n).foreach { i => 64b92f8445Sssszwic when(io.sel === i.U) { 65b92f8445Sssszwic io.out <> io.in(i) 66b92f8445Sssszwic } 67b92f8445Sssszwic io.in(i).ready := (io.sel === i.U) && io.out.ready 68b92f8445Sssszwic } 69b92f8445Sssszwic} 70b92f8445Sssszwic 71b92f8445Sssszwicclass ICacheMissReq(implicit p: Parameters) extends ICacheBundle { 72415fcbe2Sxu_zh val blkPaddr: UInt = UInt((PAddrBits - blockOffBits).W) 73415fcbe2Sxu_zh val vSetIdx: UInt = UInt(idxBits.W) 74b92f8445Sssszwic} 75b92f8445Sssszwic 76b92f8445Sssszwicclass ICacheMissResp(implicit p: Parameters) extends ICacheBundle { 77415fcbe2Sxu_zh val blkPaddr: UInt = UInt((PAddrBits - blockOffBits).W) 78415fcbe2Sxu_zh val vSetIdx: UInt = UInt(idxBits.W) 79415fcbe2Sxu_zh val waymask: UInt = UInt(nWays.W) 80415fcbe2Sxu_zh val data: UInt = UInt(blockBits.W) 81415fcbe2Sxu_zh val corrupt: Bool = Bool() 821d8f4dcbSJay} 831d8f4dcbSJay 84b92f8445Sssszwicclass LookUpMSHR(implicit p: Parameters) extends ICacheBundle { 85415fcbe2Sxu_zh val info: Valid[ICacheMissReq] = ValidIO(new ICacheMissReq) 86415fcbe2Sxu_zh val hit: Bool = Input(Bool()) 871d8f4dcbSJay} 881d8f4dcbSJay 89b92f8445Sssszwicclass MSHRResp(implicit p: Parameters) extends ICacheBundle { 90415fcbe2Sxu_zh val blkPaddr: UInt = UInt((PAddrBits - blockOffBits).W) 91415fcbe2Sxu_zh val vSetIdx: UInt = UInt(idxBits.W) 92415fcbe2Sxu_zh val way: UInt = UInt(wayBits.W) 93b92f8445Sssszwic} 94b92f8445Sssszwic 95b92f8445Sssszwicclass MSHRAcquire(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle { 96415fcbe2Sxu_zh val acquire: TLBundleA = new TLBundleA(edge.bundle) 97415fcbe2Sxu_zh val vSetIdx: UInt = UInt(idxBits.W) 98b92f8445Sssszwic} 99b92f8445Sssszwic 100415fcbe2Sxu_zhclass ICacheMSHRIO(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle { 101415fcbe2Sxu_zh val fencei: Bool = Input(Bool()) 102415fcbe2Sxu_zh val flush: Bool = Input(Bool()) 103415fcbe2Sxu_zh val invalid: Bool = Input(Bool()) 104415fcbe2Sxu_zh val req: DecoupledIO[ICacheMissReq] = Flipped(DecoupledIO(new ICacheMissReq)) 105415fcbe2Sxu_zh val acquire: DecoupledIO[MSHRAcquire] = DecoupledIO(new MSHRAcquire(edge)) 106415fcbe2Sxu_zh val lookUps: Vec[LookUpMSHR] = Flipped(Vec(2, new LookUpMSHR)) 107415fcbe2Sxu_zh val resp: Valid[MSHRResp] = ValidIO(new MSHRResp) 108415fcbe2Sxu_zh val victimWay: UInt = Input(UInt(wayBits.W)) 109415fcbe2Sxu_zh} 1101d8f4dcbSJay 111415fcbe2Sxu_zhclass ICacheMSHR(edge: TLEdgeOut, isFetch: Boolean, ID: Int)(implicit p: Parameters) extends ICacheModule { 112415fcbe2Sxu_zh val io: ICacheMSHRIO = IO(new ICacheMSHRIO(edge)) 113415fcbe2Sxu_zh 114415fcbe2Sxu_zh private val valid = RegInit(Bool(), false.B) 115415fcbe2Sxu_zh // this MSHR doesn't respond to fetch and sram 116415fcbe2Sxu_zh private val flush = RegInit(Bool(), false.B) 117415fcbe2Sxu_zh private val fencei = RegInit(Bool(), false.B) 118b92f8445Sssszwic // this MSHR has been issued 119415fcbe2Sxu_zh private val issue = RegInit(Bool(), false.B) 1201d8f4dcbSJay 121415fcbe2Sxu_zh private val blkPaddr = RegInit(UInt((PAddrBits - blockOffBits).W), 0.U) 122415fcbe2Sxu_zh private val vSetIdx = RegInit(UInt(idxBits.W), 0.U) 123415fcbe2Sxu_zh private val way = RegInit(UInt(wayBits.W), 0.U) 1241d8f4dcbSJay 125b92f8445Sssszwic // look up and return result at the same cycle 126415fcbe2Sxu_zh private val hits = io.lookUps.map { lookup => 127cf7d6b7aSMuzi valid && !fencei && !flush && (lookup.info.bits.vSetIdx === vSetIdx) && 128cf7d6b7aSMuzi (lookup.info.bits.blkPaddr === blkPaddr) 129415fcbe2Sxu_zh } 130b92f8445Sssszwic // Decoupling valid and bits 131cf7d6b7aSMuzi (0 until 2).foreach(i => io.lookUps(i).hit := hits(i)) 1321d8f4dcbSJay 133b92f8445Sssszwic // disable wake up when hit MSHR (fencei is low) 134b92f8445Sssszwic // when(hit) { 135b92f8445Sssszwic // flush := false.B 136b92f8445Sssszwic // } 1372a6078bfSguohongyu 138b92f8445Sssszwic // invalid when the req hasn't been issued 139b92f8445Sssszwic when(io.fencei || io.flush) { 140b92f8445Sssszwic fencei := true.B 141b92f8445Sssszwic flush := true.B 142b92f8445Sssszwic when(!issue) { 143b92f8445Sssszwic valid := false.B 144b92f8445Sssszwic } 145b92f8445Sssszwic } 1461d8f4dcbSJay 147b92f8445Sssszwic // receive request and register 148b92f8445Sssszwic io.req.ready := !valid && !io.flush && !io.fencei 149935edac4STang Haojin when(io.req.fire) { 150b92f8445Sssszwic valid := true.B 151b92f8445Sssszwic flush := false.B 152b92f8445Sssszwic issue := false.B 153b92f8445Sssszwic fencei := false.B 154b92f8445Sssszwic blkPaddr := io.req.bits.blkPaddr 155b92f8445Sssszwic vSetIdx := io.req.bits.vSetIdx 1561d8f4dcbSJay } 1571d8f4dcbSJay 158b92f8445Sssszwic // send request to L2 159b92f8445Sssszwic io.acquire.valid := valid && !issue && !io.flush && !io.fencei 160415fcbe2Sxu_zh private val getBlock = edge.Get( 161b92f8445Sssszwic fromSource = ID.U, 162b92f8445Sssszwic toAddress = Cat(blkPaddr, 0.U(blockOffBits.W)), 163cf7d6b7aSMuzi lgSize = log2Up(cacheParams.blockBytes).U 16438160951Sguohongyu )._2 165b92f8445Sssszwic io.acquire.bits.acquire := getBlock 166b92f8445Sssszwic io.acquire.bits.acquire.user.lift(ReqSourceKey).foreach(_ := MemReqSource.CPUInst.id.U) 167b92f8445Sssszwic io.acquire.bits.vSetIdx := vSetIdx 16838160951Sguohongyu 169b92f8445Sssszwic // get victim way when acquire fire 170b92f8445Sssszwic when(io.acquire.fire) { 171b92f8445Sssszwic issue := true.B 172415fcbe2Sxu_zh way := io.victimWay 173b92f8445Sssszwic } 1741d8f4dcbSJay 175b92f8445Sssszwic // invalid request when grant finish 176b92f8445Sssszwic when(io.invalid) { 177b92f8445Sssszwic valid := false.B 178b92f8445Sssszwic } 1792a25dbb4SJay 180b92f8445Sssszwic // offer the information other than data for write sram and response fetch 181b92f8445Sssszwic io.resp.valid := valid && (!flush && !fencei) 182b92f8445Sssszwic io.resp.bits.blkPaddr := blkPaddr 183b92f8445Sssszwic io.resp.bits.vSetIdx := vSetIdx 184415fcbe2Sxu_zh io.resp.bits.way := way 185b92f8445Sssszwic} 186131aa97cSssszwic 187415fcbe2Sxu_zhclass ICacheMissUnitIO(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle { 188b92f8445Sssszwic // difftest 189415fcbe2Sxu_zh val hartId: Bool = Input(Bool()) 190b92f8445Sssszwic // control 191415fcbe2Sxu_zh val fencei: Bool = Input(Bool()) 192415fcbe2Sxu_zh val flush: Bool = Input(Bool()) 193b92f8445Sssszwic // fetch 194415fcbe2Sxu_zh val fetch_req: DecoupledIO[ICacheMissReq] = Flipped(DecoupledIO(new ICacheMissReq)) 195415fcbe2Sxu_zh val fetch_resp: Valid[ICacheMissResp] = ValidIO(new ICacheMissResp) 196b92f8445Sssszwic // prefetch 197415fcbe2Sxu_zh val prefetch_req: DecoupledIO[ICacheMissReq] = Flipped(DecoupledIO(new ICacheMissReq)) 198b92f8445Sssszwic // SRAM Write Req 199415fcbe2Sxu_zh val meta_write: DecoupledIO[ICacheMetaWriteBundle] = DecoupledIO(new ICacheMetaWriteBundle) 200415fcbe2Sxu_zh val data_write: DecoupledIO[ICacheDataWriteBundle] = DecoupledIO(new ICacheDataWriteBundle) 201b92f8445Sssszwic // get victim from replacer 202415fcbe2Sxu_zh val victim: ReplacerVictim = new ReplacerVictim 203b92f8445Sssszwic // Tilelink 204415fcbe2Sxu_zh val mem_acquire: DecoupledIO[TLBundleA] = DecoupledIO(new TLBundleA(edge.bundle)) 205415fcbe2Sxu_zh val mem_grant: DecoupledIO[TLBundleD] = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 2061d8f4dcbSJay} 2071d8f4dcbSJay 208415fcbe2Sxu_zhclass ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheModule { 209415fcbe2Sxu_zh val io: ICacheMissUnitIO = IO(new ICacheMissUnitIO(edge)) 2101d8f4dcbSJay 211b92f8445Sssszwic /** 212b92f8445Sssszwic ****************************************************************************** 213b92f8445Sssszwic * fetch have higher priority 214b92f8445Sssszwic * fetch MSHR: lower index have a higher priority 215b92f8445Sssszwic * prefetch MSHR: the prefetchMSHRs earlier have a higher priority 216b92f8445Sssszwic * --------- -------------- ----------- 217b92f8445Sssszwic * ---fetch reg--->| Demux |-----> | fetch MSHR |------>| Arbiter |---acquire---> 218b92f8445Sssszwic * --------- -------------- ----------- 219b92f8445Sssszwic * | fetch MSHR | ^ 220b92f8445Sssszwic * -------------- | 221b92f8445Sssszwic * | 222b92f8445Sssszwic * ----------------- | 223b92f8445Sssszwic * | prefetch MSHR | | 224b92f8445Sssszwic * --------- ----------------- ----------- 225b92f8445Sssszwic * ---fetch reg--->| Demux |----> | prefetch MSHR |---->| Arbiter | 226b92f8445Sssszwic * --------- ----------------- ----------- 227b92f8445Sssszwic * | ....... | 228b92f8445Sssszwic * ----------------- 229b92f8445Sssszwic ****************************************************************************** 230b92f8445Sssszwic */ 2311d8f4dcbSJay 232415fcbe2Sxu_zh private val fetchDemux = Module(new DeMultiplexer(new ICacheMissReq, nFetchMshr)) 233415fcbe2Sxu_zh private val prefetchDemux = Module(new DeMultiplexer(new ICacheMissReq, nPrefetchMshr)) 234415fcbe2Sxu_zh private val prefetchArb = Module(new MuxBundle(new MSHRAcquire(edge), nPrefetchMshr)) 235415fcbe2Sxu_zh private val acquireArb = Module(new Arbiter(new MSHRAcquire(edge), nFetchMshr + 1)) 236cb6e5d3cSssszwic 237b92f8445Sssszwic // To avoid duplicate request reception. 238415fcbe2Sxu_zh private val fetchHit = Wire(Bool()) 239415fcbe2Sxu_zh private val prefetchHit = Wire(Bool()) 240b92f8445Sssszwic fetchDemux.io.in <> io.fetch_req 241b92f8445Sssszwic fetchDemux.io.in.valid := io.fetch_req.valid && !fetchHit 242b92f8445Sssszwic io.fetch_req.ready := fetchDemux.io.in.ready || fetchHit 243b92f8445Sssszwic prefetchDemux.io.in <> io.prefetch_req 244b92f8445Sssszwic prefetchDemux.io.in.valid := io.prefetch_req.valid && !prefetchHit 245b92f8445Sssszwic io.prefetch_req.ready := prefetchDemux.io.in.ready || prefetchHit 246b92f8445Sssszwic acquireArb.io.in.last <> prefetchArb.io.out 2471d8f4dcbSJay 248b92f8445Sssszwic // mem_acquire connect 249b92f8445Sssszwic io.mem_acquire.valid := acquireArb.io.out.valid 250b92f8445Sssszwic io.mem_acquire.bits := acquireArb.io.out.bits.acquire 251b92f8445Sssszwic acquireArb.io.out.ready := io.mem_acquire.ready 2521d8f4dcbSJay 253415fcbe2Sxu_zh private val fetchMSHRs = (0 until nFetchMshr).map { i => 254b92f8445Sssszwic val mshr = Module(new ICacheMSHR(edge, true, i)) 255b92f8445Sssszwic mshr.io.flush := false.B 256b92f8445Sssszwic mshr.io.fencei := io.fencei 257b92f8445Sssszwic mshr.io.req <> fetchDemux.io.out(i) 258b92f8445Sssszwic mshr.io.lookUps(0).info.valid := io.fetch_req.valid 259b92f8445Sssszwic mshr.io.lookUps(0).info.bits := io.fetch_req.bits 260b92f8445Sssszwic mshr.io.lookUps(1).info.valid := io.prefetch_req.valid 261b92f8445Sssszwic mshr.io.lookUps(1).info.bits := io.prefetch_req.bits 262b92f8445Sssszwic mshr.io.victimWay := io.victim.way 263b92f8445Sssszwic acquireArb.io.in(i) <> mshr.io.acquire 264b92f8445Sssszwic mshr 2651d8f4dcbSJay } 2661d8f4dcbSJay 267415fcbe2Sxu_zh private val prefetchMSHRs = (0 until nPrefetchMshr).map { i => 268b92f8445Sssszwic val mshr = Module(new ICacheMSHR(edge, false, nFetchMshr + i)) 269b92f8445Sssszwic mshr.io.flush := io.flush 270b92f8445Sssszwic mshr.io.fencei := io.fencei 271b92f8445Sssszwic mshr.io.req <> prefetchDemux.io.out(i) 272b92f8445Sssszwic mshr.io.lookUps(0).info.valid := io.fetch_req.valid 273b92f8445Sssszwic mshr.io.lookUps(0).info.bits := io.fetch_req.bits 274b92f8445Sssszwic mshr.io.lookUps(1).info.valid := io.prefetch_req.valid 275b92f8445Sssszwic mshr.io.lookUps(1).info.bits := io.prefetch_req.bits 276b92f8445Sssszwic mshr.io.victimWay := io.victim.way 277b92f8445Sssszwic prefetchArb.io.in(i) <> mshr.io.acquire 278b92f8445Sssszwic mshr 2797052722fSJay } 2807052722fSJay 28158c354d0Sssszwic /** 28258c354d0Sssszwic ****************************************************************************** 283b92f8445Sssszwic * MSHR look up 284b92f8445Sssszwic * - look up all mshr 28558c354d0Sssszwic ****************************************************************************** 28658c354d0Sssszwic */ 287415fcbe2Sxu_zh private val allMSHRs = fetchMSHRs ++ prefetchMSHRs 288415fcbe2Sxu_zh private val prefetchHitFetchReq = (io.prefetch_req.bits.blkPaddr === io.fetch_req.bits.blkPaddr) && 289b92f8445Sssszwic (io.prefetch_req.bits.vSetIdx === io.fetch_req.bits.vSetIdx) && 290b92f8445Sssszwic io.fetch_req.valid 291b92f8445Sssszwic fetchHit := allMSHRs.map(mshr => mshr.io.lookUps(0).hit).reduce(_ || _) 292b92f8445Sssszwic prefetchHit := allMSHRs.map(mshr => mshr.io.lookUps(1).hit).reduce(_ || _) || prefetchHitFetchReq 29358c354d0Sssszwic 294b92f8445Sssszwic /** 295b92f8445Sssszwic ****************************************************************************** 296b92f8445Sssszwic * prefetchMSHRs priority 297b92f8445Sssszwic * - The requests that enter the prefetchMSHRs earlier have a higher priority in issuing. 298415fcbe2Sxu_zh * - The order of enqueuing is recorded in FIFO when request enters MSHRs. 299b92f8445Sssszwic * - The requests are dispatched in the order they are recorded in FIFO. 300b92f8445Sssszwic ****************************************************************************** 301b92f8445Sssszwic */ 302b92f8445Sssszwic // When the FIFO is full, enqueue and dequeue operations do not occur at the same cycle. 303b92f8445Sssszwic // So the depth of the FIFO is set to match the number of MSHRs. 304b92f8445Sssszwic // val priorityFIFO = Module(new Queue(UInt(log2Ceil(nPrefetchMshr).W), nPrefetchMshr, hasFlush=true)) 305415fcbe2Sxu_zh private val priorityFIFO = Module(new FIFOReg(UInt(log2Ceil(nPrefetchMshr).W), nPrefetchMshr, hasFlush = true)) 306b92f8445Sssszwic priorityFIFO.io.flush.get := io.flush || io.fencei 307b92f8445Sssszwic priorityFIFO.io.enq.valid := prefetchDemux.io.in.fire 308b92f8445Sssszwic priorityFIFO.io.enq.bits := prefetchDemux.io.chosen 309b92f8445Sssszwic priorityFIFO.io.deq.ready := prefetchArb.io.out.fire 310b92f8445Sssszwic prefetchArb.io.sel := priorityFIFO.io.deq.bits 311cf7d6b7aSMuzi assert( 312cf7d6b7aSMuzi !(priorityFIFO.io.enq.fire ^ prefetchDemux.io.in.fire), 313cf7d6b7aSMuzi "priorityFIFO.io.enq and io.prefetch_req must fire at the same cycle" 314cf7d6b7aSMuzi ) 315cf7d6b7aSMuzi assert( 316cf7d6b7aSMuzi !(priorityFIFO.io.deq.fire ^ prefetchArb.io.out.fire), 317cf7d6b7aSMuzi "priorityFIFO.io.deq and prefetchArb.io.out must fire at the same cycle" 318cf7d6b7aSMuzi ) 3197052722fSJay 320b92f8445Sssszwic /** 321b92f8445Sssszwic ****************************************************************************** 322b92f8445Sssszwic * Tilelink D channel (grant) 323b92f8445Sssszwic ****************************************************************************** 324b92f8445Sssszwic */ 325b92f8445Sssszwic // cacheline register 326415fcbe2Sxu_zh private val readBeatCnt = RegInit(UInt(log2Up(refillCycles).W), 0.U) 327415fcbe2Sxu_zh private val respDataReg = RegInit(VecInit(Seq.fill(refillCycles)(0.U(beatBits.W)))) 3281d8f4dcbSJay 329415fcbe2Sxu_zh private val wait_last = readBeatCnt === (refillCycles - 1).U 330b92f8445Sssszwic when(io.mem_grant.fire && edge.hasData(io.mem_grant.bits)) { 331b92f8445Sssszwic respDataReg(readBeatCnt) := io.mem_grant.bits.data 33233a531f0Sxu_zh readBeatCnt := Mux(wait_last, 0.U, readBeatCnt + 1.U) 333b92f8445Sssszwic } 334b92f8445Sssszwic 335415fcbe2Sxu_zh // last transition finish or corrupt 336415fcbe2Sxu_zh private val last_fire = io.mem_grant.fire && edge.hasData(io.mem_grant.bits) && wait_last 337b92f8445Sssszwic 338415fcbe2Sxu_zh private val (_, _, refill_done, _) = edge.addr_inc(io.mem_grant) 339b92f8445Sssszwic assert(!(refill_done ^ last_fire), "refill not done!") 340b92f8445Sssszwic io.mem_grant.ready := true.B 341b92f8445Sssszwic 342415fcbe2Sxu_zh private val last_fire_r = RegNext(last_fire) 343415fcbe2Sxu_zh private val id_r = RegNext(io.mem_grant.bits.source) 34433a531f0Sxu_zh 34533a531f0Sxu_zh // if any beat is corrupt, the whole response (to mainPipe/metaArray/dataArray) is corrupt 346415fcbe2Sxu_zh private val corrupt_r = RegInit(false.B) 34733a531f0Sxu_zh when(io.mem_grant.fire && edge.hasData(io.mem_grant.bits) && io.mem_grant.bits.corrupt) { 348ca892e73Sxu_zh // Set corrupt_r when any beat is corrupt 349ca892e73Sxu_zh // This is actually when(xxx.fire && xxx.hasData) { corrupt_r := corrupt_r || io.mem_grant.bits.corrupt } 35033a531f0Sxu_zh corrupt_r := true.B 351ca892e73Sxu_zh }.elsewhen(last_fire_r) { 352ca892e73Sxu_zh // Clear corrupt_r when response it sent to mainPipe 353*602b407cSxu_zh // This used to be io.fetch_resp.valid (last_fire_r && mshr_valid) but when mshr is flushed by io.flush/fencei, 354*602b407cSxu_zh // mshr_valid is false.B and corrupt_r will never be cleared, that's not correct 355*602b407cSxu_zh // so we remove mshr_valid here, and the condition leftover is last_fire_r 356*602b407cSxu_zh // or, actually, io.fetch_resp.valid || (last_fire_r && !mshr_valid) 35733a531f0Sxu_zh corrupt_r := false.B 35833a531f0Sxu_zh } 359b92f8445Sssszwic 360b92f8445Sssszwic /** 361b92f8445Sssszwic ****************************************************************************** 362b92f8445Sssszwic * invalid mshr when finish transition 363b92f8445Sssszwic ****************************************************************************** 364b92f8445Sssszwic */ 365cf7d6b7aSMuzi (0 until (nFetchMshr + nPrefetchMshr)).foreach(i => allMSHRs(i).io.invalid := last_fire_r && (id_r === i.U)) 366b92f8445Sssszwic 367b92f8445Sssszwic /** 368b92f8445Sssszwic ****************************************************************************** 369b92f8445Sssszwic * response fetch and write SRAM 370b92f8445Sssszwic ****************************************************************************** 371b92f8445Sssszwic */ 372b92f8445Sssszwic // get request information from MSHRs 373415fcbe2Sxu_zh private val allMSHRs_resp = VecInit(allMSHRs.map(mshr => mshr.io.resp)) 374*602b407cSxu_zh // select MSHR response 1 cycle before sending response to mainPipe/prefetchPipe for better timing 375*602b407cSxu_zh private val mshr_resp = 376*602b407cSxu_zh RegEnable(allMSHRs_resp(io.mem_grant.bits.source).bits, 0.U.asTypeOf(allMSHRs_resp(0).bits), last_fire) 377*602b407cSxu_zh // we can latch mshr.io.resp.bits since they are set on req.fire or acquire.fire, and keeps unchanged during response 378*602b407cSxu_zh // however, we should not latch mshr.io.resp.valid, since io.flush/fencei may clear it at any time 379*602b407cSxu_zh private val mshr_valid = allMSHRs_resp(id_r).valid 380b92f8445Sssszwic 381b92f8445Sssszwic // get waymask from replacer when acquire fire 3827a63335aSxu_zh io.victim.vSetIdx.valid := acquireArb.io.out.fire 383b92f8445Sssszwic io.victim.vSetIdx.bits := acquireArb.io.out.bits.vSetIdx 384*602b407cSxu_zh private val waymask = UIntToOH(mshr_resp.way) 385adf97c94Sxu_zh // NOTE: when flush/fencei, missUnit will still send response to mainPipe/prefetchPipe 386adf97c94Sxu_zh // this is intentional to fix timing (io.flush -> mainPipe/prefetchPipe s2_miss -> s2_ready -> ftq ready) 387adf97c94Sxu_zh // unnecessary response will be dropped by mainPipe/prefetchPipe/wayLookup since their sx_valid is set to false 388*602b407cSxu_zh private val fetch_resp_valid = mshr_valid && last_fire_r 389adf97c94Sxu_zh // NOTE: but we should not write meta/dataArray when flush/fencei 390415fcbe2Sxu_zh private val write_sram_valid = fetch_resp_valid && !corrupt_r && !io.flush && !io.fencei 391b92f8445Sssszwic 392b92f8445Sssszwic // write SRAM 393cf7d6b7aSMuzi io.meta_write.bits.generate( 394*602b407cSxu_zh tag = getPhyTagFromBlk(mshr_resp.blkPaddr), 395*602b407cSxu_zh idx = mshr_resp.vSetIdx, 396b92f8445Sssszwic waymask = waymask, 397*602b407cSxu_zh bankIdx = mshr_resp.vSetIdx(0), 3986c106319Sxu_zh poison = false.B 399cf7d6b7aSMuzi ) 400cf7d6b7aSMuzi io.data_write.bits.generate( 401cf7d6b7aSMuzi data = respDataReg.asUInt, 402*602b407cSxu_zh idx = mshr_resp.vSetIdx, 403b92f8445Sssszwic waymask = waymask, 404*602b407cSxu_zh bankIdx = mshr_resp.vSetIdx(0), 4056c106319Sxu_zh poison = false.B 406cf7d6b7aSMuzi ) 407b92f8445Sssszwic 408b92f8445Sssszwic io.meta_write.valid := write_sram_valid 409b92f8445Sssszwic io.data_write.valid := write_sram_valid 410b92f8445Sssszwic 411b92f8445Sssszwic // response fetch 412b92f8445Sssszwic io.fetch_resp.valid := fetch_resp_valid 413*602b407cSxu_zh io.fetch_resp.bits.blkPaddr := mshr_resp.blkPaddr 414*602b407cSxu_zh io.fetch_resp.bits.vSetIdx := mshr_resp.vSetIdx 415b92f8445Sssszwic io.fetch_resp.bits.waymask := waymask 416b92f8445Sssszwic io.fetch_resp.bits.data := respDataReg.asUInt 417b92f8445Sssszwic io.fetch_resp.bits.corrupt := corrupt_r 418b92f8445Sssszwic 419b92f8445Sssszwic /** 420b92f8445Sssszwic ****************************************************************************** 421b92f8445Sssszwic * performance counter 422b92f8445Sssszwic ****************************************************************************** 423b92f8445Sssszwic */ 424b92f8445Sssszwic // Duplicate requests will be excluded. 425b92f8445Sssszwic XSPerfAccumulate("enq_fetch_req", fetchDemux.io.in.fire) 426b92f8445Sssszwic XSPerfAccumulate("enq_prefetch_req", prefetchDemux.io.in.fire) 427b92f8445Sssszwic 428b92f8445Sssszwic /** 429b92f8445Sssszwic ****************************************************************************** 430b92f8445Sssszwic * ChiselDB: record ICache SRAM write log 431b92f8445Sssszwic ****************************************************************************** 432b92f8445Sssszwic */ 433415fcbe2Sxu_zh private class ICacheSRAMDB(implicit p: Parameters) extends ICacheBundle { 434415fcbe2Sxu_zh val blkPaddr: UInt = UInt((PAddrBits - blockOffBits).W) 435415fcbe2Sxu_zh val vSetIdx: UInt = UInt(idxBits.W) 436415fcbe2Sxu_zh val waymask: UInt = UInt(wayBits.W) 437b92f8445Sssszwic } 438b92f8445Sssszwic 439415fcbe2Sxu_zh private val isWriteICacheSRAMTable = 440cf7d6b7aSMuzi WireInit(Constantin.createRecord("isWriteICacheSRAMTable" + p(XSCoreParamsKey).HartId.toString)) 441415fcbe2Sxu_zh private val ICacheSRAMTable = 442415fcbe2Sxu_zh ChiselDB.createTable("ICacheSRAMTable" + p(XSCoreParamsKey).HartId.toString, new ICacheSRAMDB) 443b92f8445Sssszwic 444415fcbe2Sxu_zh private val ICacheSRAMDBDumpData = Wire(new ICacheSRAMDB) 445*602b407cSxu_zh ICacheSRAMDBDumpData.blkPaddr := mshr_resp.blkPaddr 446*602b407cSxu_zh ICacheSRAMDBDumpData.vSetIdx := mshr_resp.vSetIdx 447b92f8445Sssszwic ICacheSRAMDBDumpData.waymask := OHToUInt(waymask) 448b92f8445Sssszwic ICacheSRAMTable.log( 449b92f8445Sssszwic data = ICacheSRAMDBDumpData, 450b92f8445Sssszwic en = write_sram_valid, 451b92f8445Sssszwic clock = clock, 452b92f8445Sssszwic reset = reset 453b92f8445Sssszwic ) 454b92f8445Sssszwic 455b92f8445Sssszwic /** 456b92f8445Sssszwic ****************************************************************************** 457b92f8445Sssszwic * Difftest 458b92f8445Sssszwic ****************************************************************************** 459b92f8445Sssszwic */ 460afa866b1Sguohongyu if (env.EnableDifftest) { 461a0c65233SYinan Xu val difftest = DifftestModule(new DiffRefillEvent, dontCare = true) 4627d45a146SYinan Xu difftest.coreid := io.hartId 4637d45a146SYinan Xu difftest.index := 0.U 464b92f8445Sssszwic difftest.valid := write_sram_valid 465*602b407cSxu_zh difftest.addr := Cat(mshr_resp.blkPaddr, 0.U(blockOffBits.W)) 466b92f8445Sssszwic difftest.data := respDataReg.asTypeOf(difftest.data) 467935edac4STang Haojin difftest.idtfr := DontCare 46841cb8b61SJenius } 4691d8f4dcbSJay} 470