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._ 217d45a146SYinan Xuimport difftest._ 22cf7d6b7aSMuziimport org.chipsalliance.cde.config.Parameters 233c02ee8fSwakafaimport utility._ 24cf7d6b7aSMuziimport xiangshan._ 25cf7d6b7aSMuziimport xiangshan.backend.fu.PMPReqBundle 26cf7d6b7aSMuziimport xiangshan.backend.fu.PMPRespBundle 27cf7d6b7aSMuziimport xiangshan.cache.mmu._ 28cf7d6b7aSMuziimport xiangshan.frontend.ExceptionType 29cf7d6b7aSMuziimport xiangshan.frontend.FtqToICacheRequestBundle 301d8f4dcbSJay 31cf7d6b7aSMuziclass ICacheMainPipeResp(implicit p: Parameters) extends ICacheBundle { 32*415fcbe2Sxu_zh val doubleline: Bool = Bool() 33*415fcbe2Sxu_zh val vaddr: Vec[UInt] = Vec(PortNumber, UInt(VAddrBits.W)) 34*415fcbe2Sxu_zh val data: UInt = UInt(blockBits.W) 35*415fcbe2Sxu_zh val paddr: Vec[UInt] = Vec(PortNumber, UInt(PAddrBits.W)) 36*415fcbe2Sxu_zh val exception: Vec[UInt] = Vec(PortNumber, UInt(ExceptionType.width.W)) 37*415fcbe2Sxu_zh val pmp_mmio: Vec[Bool] = Vec(PortNumber, Bool()) 38*415fcbe2Sxu_zh val itlb_pbmt: Vec[UInt] = Vec(PortNumber, UInt(Pbmt.width.W)) 39*415fcbe2Sxu_zh val backendException: Bool = Bool() 40dd980d61SXu, Zefan /* NOTE: GPAddrBits(=50bit) is not enough for gpaddr here, refer to PR#3795 41dd980d61SXu, Zefan * Sv48*4 only allows 50bit gpaddr, when software violates this requirement 42dd980d61SXu, Zefan * it needs to fill the mtval2 register with the full XLEN(=64bit) gpaddr, 43dd980d61SXu, Zefan * PAddrBitsMax(=56bit currently) is required for the frontend datapath due to the itlb ppn length limitation 44dd980d61SXu, Zefan * (cases 56<x<=64 are handled by the backend datapath) 45dd980d61SXu, Zefan */ 46*415fcbe2Sxu_zh val gpaddr: UInt = UInt(PAddrBitsMax.W) 47*415fcbe2Sxu_zh val isForVSnonLeafPTE: Bool = Bool() 481d8f4dcbSJay} 491d8f4dcbSJay 50cf7d6b7aSMuziclass ICacheMainPipeBundle(implicit p: Parameters) extends ICacheBundle { 51*415fcbe2Sxu_zh val req: DecoupledIO[FtqToICacheRequestBundle] = Flipped(DecoupledIO(new FtqToICacheRequestBundle)) 52*415fcbe2Sxu_zh val resp: Valid[ICacheMainPipeResp] = ValidIO(new ICacheMainPipeResp) 53*415fcbe2Sxu_zh val topdownIcacheMiss: Bool = Output(Bool()) 54*415fcbe2Sxu_zh val topdownItlbMiss: Bool = Output(Bool()) 551d8f4dcbSJay} 561d8f4dcbSJay 571d8f4dcbSJayclass ICacheMetaReqBundle(implicit p: Parameters) extends ICacheBundle { 58*415fcbe2Sxu_zh val toIMeta: DecoupledIO[ICacheReadBundle] = DecoupledIO(new ICacheReadBundle) 59*415fcbe2Sxu_zh val fromIMeta: ICacheMetaRespBundle = Input(new ICacheMetaRespBundle) 601d8f4dcbSJay} 611d8f4dcbSJay 621d8f4dcbSJayclass ICacheDataReqBundle(implicit p: Parameters) extends ICacheBundle { 63*415fcbe2Sxu_zh val toIData: Vec[DecoupledIO[ICacheReadBundle]] = Vec(partWayNum, DecoupledIO(new ICacheReadBundle)) 64*415fcbe2Sxu_zh val fromIData: ICacheDataRespBundle = Input(new ICacheDataRespBundle) 651d8f4dcbSJay} 661d8f4dcbSJay 671d8f4dcbSJayclass ICacheMSHRBundle(implicit p: Parameters) extends ICacheBundle { 68*415fcbe2Sxu_zh val req: DecoupledIO[ICacheMissReq] = DecoupledIO(new ICacheMissReq) 69*415fcbe2Sxu_zh val resp: Valid[ICacheMissResp] = Flipped(ValidIO(new ICacheMissResp)) 701d8f4dcbSJay} 711d8f4dcbSJay 721d8f4dcbSJayclass ICachePMPBundle(implicit p: Parameters) extends ICacheBundle { 73*415fcbe2Sxu_zh val req: Valid[PMPReqBundle] = ValidIO(new PMPReqBundle()) 74*415fcbe2Sxu_zh val resp: PMPRespBundle = Input(new PMPRespBundle()) 751d8f4dcbSJay} 761d8f4dcbSJay 771d8f4dcbSJayclass ICachePerfInfo(implicit p: Parameters) extends ICacheBundle { 78*415fcbe2Sxu_zh val only_0_hit: Bool = Bool() 79*415fcbe2Sxu_zh val only_0_miss: Bool = Bool() 80*415fcbe2Sxu_zh val hit_0_hit_1: Bool = Bool() 81*415fcbe2Sxu_zh val hit_0_miss_1: Bool = Bool() 82*415fcbe2Sxu_zh val miss_0_hit_1: Bool = Bool() 83*415fcbe2Sxu_zh val miss_0_miss_1: Bool = Bool() 84*415fcbe2Sxu_zh val hit_0_except_1: Bool = Bool() 85*415fcbe2Sxu_zh val miss_0_except_1: Bool = Bool() 86*415fcbe2Sxu_zh val except_0: Bool = Bool() 87*415fcbe2Sxu_zh val bank_hit: Vec[Bool] = Vec(PortNumber, Bool()) 88*415fcbe2Sxu_zh val hit: Bool = Bool() 891d8f4dcbSJay} 901d8f4dcbSJay 911d8f4dcbSJayclass ICacheMainPipeInterface(implicit p: Parameters) extends ICacheBundle { 92*415fcbe2Sxu_zh val hartId: UInt = Input(UInt(hartIdLen.W)) 93cf7d6b7aSMuzi 942a3050c2SJay /*** internal interface ***/ 95*415fcbe2Sxu_zh val dataArray: ICacheDataReqBundle = new ICacheDataReqBundle 96*415fcbe2Sxu_zh val metaArrayFlush: Vec[Valid[ICacheMetaFlushBundle]] = Vec(PortNumber, ValidIO(new ICacheMetaFlushBundle)) 97*415fcbe2Sxu_zh val touch: Vec[Valid[ReplacerTouch]] = Vec(PortNumber, ValidIO(new ReplacerTouch)) 98*415fcbe2Sxu_zh val wayLookupRead: DecoupledIO[WayLookupInfo] = Flipped(DecoupledIO(new WayLookupInfo)) 99*415fcbe2Sxu_zh val mshr: ICacheMSHRBundle = new ICacheMSHRBundle 100cf7d6b7aSMuzi 1012a3050c2SJay /*** outside interface ***/ 102*415fcbe2Sxu_zh // FTQ 103*415fcbe2Sxu_zh val fetch: ICacheMainPipeBundle = new ICacheMainPipeBundle 104*415fcbe2Sxu_zh val flush: Bool = Input(Bool()) 105*415fcbe2Sxu_zh // PMP 106*415fcbe2Sxu_zh val pmp: Vec[ICachePMPBundle] = Vec(PortNumber, new ICachePMPBundle) 107*415fcbe2Sxu_zh // IFU 108*415fcbe2Sxu_zh val respStall: Bool = Input(Bool()) 109*415fcbe2Sxu_zh // backend/BEU 110*415fcbe2Sxu_zh val errors: Vec[Valid[L1CacheErrorInfo]] = Output(Vec(PortNumber, ValidIO(new L1CacheErrorInfo))) 111*415fcbe2Sxu_zh // backend/CSR 112*415fcbe2Sxu_zh val csr_parity_enable: Bool = Input(Bool()) 11358dbdfc2SJay 114*415fcbe2Sxu_zh /*** PERF ***/ 115*415fcbe2Sxu_zh val perfInfo: ICachePerfInfo = Output(new ICachePerfInfo) 1161d8f4dcbSJay} 1171d8f4dcbSJay 118*415fcbe2Sxu_zh//class ICacheDB(implicit p: Parameters) extends ICacheBundle { 119*415fcbe2Sxu_zh// val blk_vaddr: UInt = UInt((VAddrBits - blockOffBits).W) 120*415fcbe2Sxu_zh// val blk_paddr: UInt = UInt((PAddrBits - blockOffBits).W) 121*415fcbe2Sxu_zh// val hit: Bool = Bool() 122*415fcbe2Sxu_zh//} 123f9c51548Sssszwic 124cf7d6b7aSMuziclass ICacheMainPipe(implicit p: Parameters) extends ICacheModule { 125*415fcbe2Sxu_zh val io: ICacheMainPipeInterface = IO(new ICacheMainPipeInterface) 1261d8f4dcbSJay 12758dbdfc2SJay /** Input/Output port */ 128*415fcbe2Sxu_zh private val (fromFtq, toIFU) = (io.fetch.req, io.fetch.resp) 129*415fcbe2Sxu_zh private val (toData, fromData) = (io.dataArray.toIData, io.dataArray.fromIData) 130*415fcbe2Sxu_zh private val toMetaFlush = io.metaArrayFlush 131*415fcbe2Sxu_zh private val (toMSHR, fromMSHR) = (io.mshr.req, io.mshr.resp) 132*415fcbe2Sxu_zh private val (toPMP, fromPMP) = (io.pmp.map(_.req), io.pmp.map(_.resp)) 133*415fcbe2Sxu_zh private val fromWayLookup = io.wayLookupRead 134*415fcbe2Sxu_zh private val csr_parity_enable = 135*415fcbe2Sxu_zh if (ICacheForceMetaECCError || ICacheForceDataECCError) true.B else io.csr_parity_enable 13658c354d0Sssszwic 13758c354d0Sssszwic // Statistics on the frequency distribution of FTQ fire interval 138*415fcbe2Sxu_zh private val cntFtqFireInterval = RegInit(0.U(32.W)) 139*415fcbe2Sxu_zh private val cntFtqFireIntervalStart = 1 140*415fcbe2Sxu_zh private val cntFtqFireIntervalEnd = 300 14158c354d0Sssszwic cntFtqFireInterval := Mux(fromFtq.fire, 1.U, cntFtqFireInterval + 1.U) 142*415fcbe2Sxu_zh XSPerfHistogram( 143*415fcbe2Sxu_zh "ftq2icache_fire", 144*415fcbe2Sxu_zh cntFtqFireInterval, 145*415fcbe2Sxu_zh fromFtq.fire, 146*415fcbe2Sxu_zh cntFtqFireIntervalStart, 147*415fcbe2Sxu_zh cntFtqFireIntervalEnd, 148*415fcbe2Sxu_zh right_strict = true 149*415fcbe2Sxu_zh ) 150b1ded4e8Sguohongyu 15158dbdfc2SJay /** pipeline control signal */ 152f1fe8698SLemover val s1_ready, s2_ready = Wire(Bool()) 153f1fe8698SLemover val s0_fire, s1_fire, s2_fire = Wire(Bool()) 154b92f8445Sssszwic val s0_flush, s1_flush, s2_flush = Wire(Bool()) 1551d8f4dcbSJay 1562a3050c2SJay /** 1572a3050c2SJay ****************************************************************************** 15858dbdfc2SJay * ICache Stage 0 159b92f8445Sssszwic * - send req to data SRAM 160b92f8445Sssszwic * - get waymask and tlb info from wayLookup 1612a3050c2SJay ****************************************************************************** 1622a3050c2SJay */ 1632a3050c2SJay 16458dbdfc2SJay /** s0 control */ 165b92f8445Sssszwic // 0,1,2,3 -> dataArray(data); 4 -> mainPipe 166b92f8445Sssszwic // Ftq RegNext Register 167*415fcbe2Sxu_zh private val fromFtqReq = fromFtq.bits.pcMemRead 168*415fcbe2Sxu_zh private val s0_valid = fromFtq.valid 169*415fcbe2Sxu_zh private val s0_req_valid_all = (0 until partWayNum + 1).map(i => fromFtq.bits.readValid(i)) 170*415fcbe2Sxu_zh private val s0_req_vaddr_all = 171cf7d6b7aSMuzi (0 until partWayNum + 1).map(i => VecInit(Seq(fromFtqReq(i).startAddr, fromFtqReq(i).nextlineStart))) 172*415fcbe2Sxu_zh private val s0_req_vSetIdx_all = (0 until partWayNum + 1).map(i => VecInit(s0_req_vaddr_all(i).map(get_idx))) 173*415fcbe2Sxu_zh private val s0_req_offset_all = (0 until partWayNum + 1).map(i => s0_req_vaddr_all(i)(0)(log2Ceil(blockBytes) - 1, 0)) 174*415fcbe2Sxu_zh private val s0_doubleline_all = 175*415fcbe2Sxu_zh (0 until partWayNum + 1).map(i => fromFtq.bits.readValid(i) && fromFtqReq(i).crossCacheline) 1761d8f4dcbSJay 177*415fcbe2Sxu_zh private val s0_req_vaddr = s0_req_vaddr_all.last 178*415fcbe2Sxu_zh private val s0_req_vSetIdx = s0_req_vSetIdx_all.last 179*415fcbe2Sxu_zh private val s0_doubleline = s0_doubleline_all.last 18061e1db30SJay 181*415fcbe2Sxu_zh private val s0_backendException = fromFtq.bits.backendException 182c1b28b66STang Haojin 183b92f8445Sssszwic /** 184b92f8445Sssszwic ****************************************************************************** 185b92f8445Sssszwic * get waymask and tlb info from wayLookup 186b92f8445Sssszwic ****************************************************************************** 187b92f8445Sssszwic */ 188b92f8445Sssszwic fromWayLookup.ready := s0_fire 189*415fcbe2Sxu_zh private val s0_waymasks = VecInit(fromWayLookup.bits.waymask.map(_.asTypeOf(Vec(nWays, Bool())))) 190*415fcbe2Sxu_zh private val s0_req_ptags = fromWayLookup.bits.ptag 191*415fcbe2Sxu_zh private val s0_req_gpaddr = fromWayLookup.bits.gpaddr 192*415fcbe2Sxu_zh private val s0_req_isForVSnonLeafPTE = fromWayLookup.bits.isForVSnonLeafPTE 193*415fcbe2Sxu_zh private val s0_itlb_exception = fromWayLookup.bits.itlb_exception 194*415fcbe2Sxu_zh private val s0_itlb_pbmt = fromWayLookup.bits.itlb_pbmt 195*415fcbe2Sxu_zh private val s0_meta_codes = fromWayLookup.bits.meta_codes 196*415fcbe2Sxu_zh private val s0_hits = VecInit(fromWayLookup.bits.waymask.map(_.orR)) 197f56177cbSJenius 198b92f8445Sssszwic when(s0_fire) { 199cf7d6b7aSMuzi assert( 200cf7d6b7aSMuzi (0 until PortNumber).map(i => s0_req_vSetIdx(i) === fromWayLookup.bits.vSetIdx(i)).reduce(_ && _), 201*415fcbe2Sxu_zh "vSetIdx from ftq and wayLookup mismatch! vaddr=0x%x ftq: vSet0=0x%x vSet1=0x%x wayLookup: vSet0=0x%x vSet1=0x%x", 202cf7d6b7aSMuzi s0_req_vaddr(0), 203cf7d6b7aSMuzi s0_req_vSetIdx(0), 204cf7d6b7aSMuzi s0_req_vSetIdx(1), 205cf7d6b7aSMuzi fromWayLookup.bits.vSetIdx(0), 206cf7d6b7aSMuzi fromWayLookup.bits.vSetIdx(1) 207cf7d6b7aSMuzi ) 2081d8f4dcbSJay } 209afed18b5SJenius 210b92f8445Sssszwic /** 211b92f8445Sssszwic ****************************************************************************** 212b92f8445Sssszwic * data SRAM request 213b92f8445Sssszwic ****************************************************************************** 214b92f8445Sssszwic */ 215*415fcbe2Sxu_zh (0 until partWayNum).foreach { i => 216b92f8445Sssszwic toData(i).valid := s0_req_valid_all(i) 217b92f8445Sssszwic toData(i).bits.isDoubleLine := s0_doubleline_all(i) 218b92f8445Sssszwic toData(i).bits.vSetIdx := s0_req_vSetIdx_all(i) 219b92f8445Sssszwic toData(i).bits.blkOffset := s0_req_offset_all(i) 220*415fcbe2Sxu_zh toData(i).bits.waymask := s0_waymasks 221b92f8445Sssszwic } 222afed18b5SJenius 223*415fcbe2Sxu_zh private val s0_can_go = toData.last.ready && fromWayLookup.valid && s1_ready 224b92f8445Sssszwic s0_flush := io.flush 225b92f8445Sssszwic s0_fire := s0_valid && s0_can_go && !s0_flush 2262a3050c2SJay 227c5c5edaeSJenius fromFtq.ready := s0_can_go 228f1fe8698SLemover 2292a3050c2SJay /** 2302a3050c2SJay ****************************************************************************** 23158dbdfc2SJay * ICache Stage 1 232b92f8445Sssszwic * - PMP check 233b92f8445Sssszwic * - get Data SRAM read responses (latched for pipeline stop) 234b92f8445Sssszwic * - monitor missUint response port 2352a3050c2SJay ****************************************************************************** 2362a3050c2SJay */ 237*415fcbe2Sxu_zh private val s1_valid = 238*415fcbe2Sxu_zh generatePipeControl(lastFire = s0_fire, thisFire = s1_fire, thisFlush = s1_flush, lastFlush = false.B) 2391d8f4dcbSJay 240*415fcbe2Sxu_zh private val s1_req_vaddr = RegEnable(s0_req_vaddr, 0.U.asTypeOf(s0_req_vaddr), s0_fire) 241*415fcbe2Sxu_zh private val s1_req_ptags = RegEnable(s0_req_ptags, 0.U.asTypeOf(s0_req_ptags), s0_fire) 242*415fcbe2Sxu_zh private val s1_req_gpaddr = RegEnable(s0_req_gpaddr, 0.U.asTypeOf(s0_req_gpaddr), s0_fire) 243*415fcbe2Sxu_zh private val s1_req_isForVSnonLeafPTE = 244*415fcbe2Sxu_zh RegEnable(s0_req_isForVSnonLeafPTE, 0.U.asTypeOf(s0_req_isForVSnonLeafPTE), s0_fire) 245*415fcbe2Sxu_zh private val s1_doubleline = RegEnable(s0_doubleline, 0.U.asTypeOf(s0_doubleline), s0_fire) 246*415fcbe2Sxu_zh private val s1_SRAMhits = RegEnable(s0_hits, 0.U.asTypeOf(s0_hits), s0_fire) 247*415fcbe2Sxu_zh private val s1_itlb_exception = RegEnable(s0_itlb_exception, 0.U.asTypeOf(s0_itlb_exception), s0_fire) 248*415fcbe2Sxu_zh private val s1_backendException = RegEnable(s0_backendException, false.B, s0_fire) 249*415fcbe2Sxu_zh private val s1_itlb_pbmt = RegEnable(s0_itlb_pbmt, 0.U.asTypeOf(s0_itlb_pbmt), s0_fire) 250*415fcbe2Sxu_zh private val s1_waymasks = RegEnable(s0_waymasks, 0.U.asTypeOf(s0_waymasks), s0_fire) 251*415fcbe2Sxu_zh private val s1_meta_codes = RegEnable(s0_meta_codes, 0.U.asTypeOf(s0_meta_codes), s0_fire) 2521d8f4dcbSJay 253*415fcbe2Sxu_zh private val s1_req_vSetIdx = s1_req_vaddr.map(get_idx) 254*415fcbe2Sxu_zh private val s1_req_paddr = getPaddrFromPtag(s1_req_vaddr, s1_req_ptags) 255*415fcbe2Sxu_zh private val s1_req_offset = s1_req_vaddr(0)(log2Ceil(blockBytes) - 1, 0) 256b1ded4e8Sguohongyu 2578966a895Sxu_zh // do metaArray ECC check 258*415fcbe2Sxu_zh private val s1_meta_corrupt = VecInit((s1_req_ptags zip s1_meta_codes zip s1_waymasks).map { 259*415fcbe2Sxu_zh case ((meta, code), waymask) => 2608966a895Sxu_zh val hit_num = PopCount(waymask) 2618966a895Sxu_zh // NOTE: if not hit, encodeMetaECC(meta) =/= code can also be true, but we don't care about it 2628966a895Sxu_zh (encodeMetaECC(meta) =/= code && hit_num === 1.U) || // hit one way, but parity code does not match, ECC failure 263*415fcbe2Sxu_zh hit_num > 1.U // hit multi-way, must be an ECC failure 2648966a895Sxu_zh }) 265e39d6828Sxu_zh // force clear meta_corrupt when parity check is disabled 266e39d6828Sxu_zh when(!csr_parity_enable) { 267e39d6828Sxu_zh s1_meta_corrupt := VecInit(Seq.fill(PortNumber)(false.B)) 268e39d6828Sxu_zh } 2698966a895Sxu_zh 2702a3050c2SJay /** 2712a3050c2SJay ****************************************************************************** 272b92f8445Sssszwic * update replacement status register 2732a3050c2SJay ****************************************************************************** 2742a3050c2SJay */ 275b92f8445Sssszwic (0 until PortNumber).foreach { i => 276b92f8445Sssszwic io.touch(i).bits.vSetIdx := s1_req_vSetIdx(i) 277b92f8445Sssszwic io.touch(i).bits.way := OHToUInt(s1_waymasks(i)) 278b92f8445Sssszwic } 279b92f8445Sssszwic io.touch(0).valid := RegNext(s0_fire) && s1_SRAMhits(0) 280b92f8445Sssszwic io.touch(1).valid := RegNext(s0_fire) && s1_SRAMhits(1) && s1_doubleline 281f1fe8698SLemover 282a61a35e0Sssszwic /** 283a61a35e0Sssszwic ****************************************************************************** 284b92f8445Sssszwic * PMP check 285a61a35e0Sssszwic ****************************************************************************** 286a61a35e0Sssszwic */ 28788895b11Sxu_zh toPMP.zipWithIndex.foreach { case (p, i) => 288*415fcbe2Sxu_zh // if itlb has exception, paddr can be invalid, therefore pmp check can be skipped do not do this now for timing 289dd02bc3fSxu_zh p.valid := s1_valid // && !ExceptionType.hasException(s1_itlb_exception(i)) 290b92f8445Sssszwic p.bits.addr := s1_req_paddr(i) 291*415fcbe2Sxu_zh p.bits.size := 3.U 292a61a35e0Sssszwic p.bits.cmd := TlbCmd.exec 293a61a35e0Sssszwic } 294*415fcbe2Sxu_zh private val s1_pmp_exception = VecInit(fromPMP.map(ExceptionType.fromPMPResp)) 295*415fcbe2Sxu_zh private val s1_pmp_mmio = VecInit(fromPMP.map(_.mmio)) 29688895b11Sxu_zh 297e39d6828Sxu_zh // merge s1 itlb/pmp exceptions, itlb has the highest priority, pmp next 298*415fcbe2Sxu_zh private val s1_exception_out = ExceptionType.merge( 299f80535c3Sxu_zh s1_itlb_exception, 300e39d6828Sxu_zh s1_pmp_exception 301f80535c3Sxu_zh ) 3021d8f4dcbSJay 303a61a35e0Sssszwic /** 304a61a35e0Sssszwic ****************************************************************************** 305b92f8445Sssszwic * select data from MSHR, SRAM 306a61a35e0Sssszwic ****************************************************************************** 307a61a35e0Sssszwic */ 308*415fcbe2Sxu_zh private val s1_MSHR_match = VecInit((0 until PortNumber).map { i => 309cf7d6b7aSMuzi (s1_req_vSetIdx(i) === fromMSHR.bits.vSetIdx) && 310b92f8445Sssszwic (s1_req_ptags(i) === getPhyTagFromBlk(fromMSHR.bits.blkPaddr)) && 311cf7d6b7aSMuzi fromMSHR.valid && !fromMSHR.bits.corrupt 312*415fcbe2Sxu_zh }) 313*415fcbe2Sxu_zh private val s1_MSHR_hits = Seq(s1_valid && s1_MSHR_match(0), s1_valid && (s1_MSHR_match(1) && s1_doubleline)) 314*415fcbe2Sxu_zh private val s1_MSHR_datas = fromMSHR.bits.data.asTypeOf(Vec(ICacheDataBanks, UInt((blockBits / ICacheDataBanks).W))) 31579b191f7SJay 316*415fcbe2Sxu_zh private val s1_hits = (0 until PortNumber).map { i => 317cf7d6b7aSMuzi ValidHoldBypass(s1_MSHR_hits(i) || (RegNext(s0_fire) && s1_SRAMhits(i)), s1_fire || s1_flush) 318*415fcbe2Sxu_zh } 319a61a35e0Sssszwic 320*415fcbe2Sxu_zh private val s1_bankIdxLow = (s1_req_offset >> log2Ceil(blockBytes / ICacheDataBanks)).asUInt 321*415fcbe2Sxu_zh private val s1_bankMSHRHit = VecInit((0 until ICacheDataBanks).map { i => 322cf7d6b7aSMuzi (i.U >= s1_bankIdxLow) && s1_MSHR_hits(0) || 323cf7d6b7aSMuzi (i.U < s1_bankIdxLow) && s1_MSHR_hits(1) 324*415fcbe2Sxu_zh }) 325*415fcbe2Sxu_zh private val s1_datas = VecInit((0 until ICacheDataBanks).map { i => 326cf7d6b7aSMuzi DataHoldBypass(Mux(s1_bankMSHRHit(i), s1_MSHR_datas(i), fromData.datas(i)), s1_bankMSHRHit(i) || RegNext(s0_fire)) 327*415fcbe2Sxu_zh }) 328*415fcbe2Sxu_zh private val s1_data_is_from_MSHR = VecInit((0 until ICacheDataBanks).map { i => 329e39d6828Sxu_zh DataHoldBypass(s1_bankMSHRHit(i), s1_bankMSHRHit(i) || RegNext(s0_fire)) 330*415fcbe2Sxu_zh }) 331*415fcbe2Sxu_zh private val s1_codes = DataHoldBypass(fromData.codes, RegNext(s0_fire)) 332a61a35e0Sssszwic 333b92f8445Sssszwic s1_flush := io.flush 334b92f8445Sssszwic s1_ready := s2_ready || !s1_valid 335b92f8445Sssszwic s1_fire := s1_valid && s2_ready && !s1_flush 336a61a35e0Sssszwic 337a61a35e0Sssszwic /** 338a61a35e0Sssszwic ****************************************************************************** 339b92f8445Sssszwic * ICache Stage 2 340b92f8445Sssszwic * - send request to MSHR if ICache miss 341b92f8445Sssszwic * - monitor missUint response port 342b92f8445Sssszwic * - response to IFU 343a61a35e0Sssszwic ****************************************************************************** 344a61a35e0Sssszwic */ 345a61a35e0Sssszwic 346*415fcbe2Sxu_zh private val s2_valid = 347*415fcbe2Sxu_zh generatePipeControl(lastFire = s1_fire, thisFire = s2_fire, thisFlush = s2_flush, lastFlush = false.B) 348a61a35e0Sssszwic 349*415fcbe2Sxu_zh private val s2_req_vaddr = RegEnable(s1_req_vaddr, 0.U.asTypeOf(s1_req_vaddr), s1_fire) 350*415fcbe2Sxu_zh private val s2_req_ptags = RegEnable(s1_req_ptags, 0.U.asTypeOf(s1_req_ptags), s1_fire) 351*415fcbe2Sxu_zh private val s2_req_gpaddr = RegEnable(s1_req_gpaddr, 0.U.asTypeOf(s1_req_gpaddr), s1_fire) 352*415fcbe2Sxu_zh private val s2_req_isForVSnonLeafPTE = 353*415fcbe2Sxu_zh RegEnable(s1_req_isForVSnonLeafPTE, 0.U.asTypeOf(s1_req_isForVSnonLeafPTE), s1_fire) 354*415fcbe2Sxu_zh private val s2_doubleline = RegEnable(s1_doubleline, 0.U.asTypeOf(s1_doubleline), s1_fire) 355*415fcbe2Sxu_zh private val s2_exception = RegEnable(s1_exception_out, 0.U.asTypeOf(s1_exception_out), s1_fire) 356*415fcbe2Sxu_zh private val s2_backendException = RegEnable(s1_backendException, false.B, s1_fire) 357*415fcbe2Sxu_zh private val s2_pmp_mmio = RegEnable(s1_pmp_mmio, 0.U.asTypeOf(s1_pmp_mmio), s1_fire) 358*415fcbe2Sxu_zh private val s2_itlb_pbmt = RegEnable(s1_itlb_pbmt, 0.U.asTypeOf(s1_itlb_pbmt), s1_fire) 359*415fcbe2Sxu_zh private val s2_waymasks = RegEnable(s1_waymasks, 0.U.asTypeOf(s1_waymasks), s1_fire) 360a61a35e0Sssszwic 361*415fcbe2Sxu_zh private val s2_req_vSetIdx = s2_req_vaddr.map(get_idx) 362*415fcbe2Sxu_zh private val s2_req_offset = s2_req_vaddr(0)(log2Ceil(blockBytes) - 1, 0) 363*415fcbe2Sxu_zh private val s2_req_paddr = getPaddrFromPtag(s2_req_vaddr, s2_req_ptags) 364a61a35e0Sssszwic 365*415fcbe2Sxu_zh private val s2_SRAMhits = RegEnable(s1_SRAMhits, 0.U.asTypeOf(s1_SRAMhits), s1_fire) 366*415fcbe2Sxu_zh private val s2_codes = RegEnable(s1_codes, 0.U.asTypeOf(s1_codes), s1_fire) 367*415fcbe2Sxu_zh private val s2_hits = RegInit(VecInit(Seq.fill(PortNumber)(false.B))) 368*415fcbe2Sxu_zh private val s2_datas = RegInit(VecInit(Seq.fill(ICacheDataBanks)(0.U((blockBits / ICacheDataBanks).W)))) 369*415fcbe2Sxu_zh private val s2_data_is_from_MSHR = RegInit(VecInit(Seq.fill(ICacheDataBanks)(false.B))) 370a61a35e0Sssszwic 371a61a35e0Sssszwic /** 372a61a35e0Sssszwic ****************************************************************************** 373e39d6828Sxu_zh * ECC check 374a61a35e0Sssszwic ****************************************************************************** 375a61a35e0Sssszwic */ 376b92f8445Sssszwic // check data error 377*415fcbe2Sxu_zh private val s2_bankSel = getBankSel(s2_req_offset, s2_valid) 378*415fcbe2Sxu_zh private val s2_bank_corrupt = (0 until ICacheDataBanks).map(i => encodeDataECC(s2_datas(i)) =/= s2_codes(i)) 379e39d6828Sxu_zh // if data is from MSHR, we don't need to check ECC 380*415fcbe2Sxu_zh private val s2_data_corrupt = VecInit((0 until PortNumber).map { port => 381*415fcbe2Sxu_zh (0 until ICacheDataBanks).map { bank => 382e39d6828Sxu_zh s2_bank_corrupt(bank) && s2_bankSel(port)(bank).asBool && !s2_data_is_from_MSHR(bank) 383*415fcbe2Sxu_zh }.reduce(_ || _) && s2_SRAMhits(port) 384*415fcbe2Sxu_zh }) 385e39d6828Sxu_zh // force clear data_corrupt when parity check is disabled 386e39d6828Sxu_zh when(!csr_parity_enable) { 387e39d6828Sxu_zh s2_data_corrupt := VecInit(Seq.fill(PortNumber)(false.B)) 388e39d6828Sxu_zh } 389e39d6828Sxu_zh // meta error is checked in s1 stage 390*415fcbe2Sxu_zh private val s2_meta_corrupt = RegEnable(s1_meta_corrupt, 0.U.asTypeOf(s1_meta_corrupt), s1_fire) 391b92f8445Sssszwic // send errors to top 392e39d6828Sxu_zh // TODO: support RERI spec standard interface 393*415fcbe2Sxu_zh (0 until PortNumber).foreach { i => 394e39d6828Sxu_zh io.errors(i).valid := (s2_meta_corrupt(i) || s2_data_corrupt(i)) && RegNext(s1_fire) 395e39d6828Sxu_zh io.errors(i).bits.report_to_beu := (s2_meta_corrupt(i) || s2_data_corrupt(i)) && RegNext(s1_fire) 396b92f8445Sssszwic io.errors(i).bits.paddr := s2_req_paddr(i) 3970184a80eSYanqin Li io.errors(i).bits.source := DontCare 39888895b11Sxu_zh io.errors(i).bits.source.tag := s2_meta_corrupt(i) 39988895b11Sxu_zh io.errors(i).bits.source.data := s2_data_corrupt(i) 4000184a80eSYanqin Li io.errors(i).bits.source.l2 := false.B 4010184a80eSYanqin Li io.errors(i).bits.opType := DontCare 4020184a80eSYanqin Li io.errors(i).bits.opType.fetch := true.B 40379b191f7SJay } 404e39d6828Sxu_zh // flush metaArray to prepare for re-fetch 405e39d6828Sxu_zh (0 until PortNumber).foreach { i => 406e39d6828Sxu_zh toMetaFlush(i).valid := (s2_meta_corrupt(i) || s2_data_corrupt(i)) && RegNext(s1_fire) 407e39d6828Sxu_zh toMetaFlush(i).bits.virIdx := s2_req_vSetIdx(i) 408e39d6828Sxu_zh // if is meta corrupt, clear all way (since waymask may be unreliable) 409e39d6828Sxu_zh // if is data corrupt, only clear the way that has error 410e39d6828Sxu_zh toMetaFlush(i).bits.waymask := Mux(s2_meta_corrupt(i), Fill(nWays, true.B), s2_waymasks(i).asUInt) 411e39d6828Sxu_zh } 412e39d6828Sxu_zh // PERF: count the number of data parity errors 413e39d6828Sxu_zh XSPerfAccumulate("data_corrupt_0", s2_data_corrupt(0) && RegNext(s1_fire)) 414e39d6828Sxu_zh XSPerfAccumulate("data_corrupt_1", s2_data_corrupt(1) && RegNext(s1_fire)) 415e39d6828Sxu_zh XSPerfAccumulate("meta_corrupt_0", s2_meta_corrupt(0) && RegNext(s1_fire)) 416e39d6828Sxu_zh XSPerfAccumulate("meta_corrupt_1", s2_meta_corrupt(1) && RegNext(s1_fire)) 417e39d6828Sxu_zh // TEST: stop simulation if parity error is detected, and dump wave 418e39d6828Sxu_zh// val (assert_valid, assert_val) = DelayNWithValid(s2_meta_corrupt.reduce(_ || _), s2_valid, 1000) 419e39d6828Sxu_zh// assert(!(assert_valid && assert_val)) 420e39d6828Sxu_zh// val (assert_valid, assert_val) = DelayNWithValid(s2_data_corrupt.reduce(_ || _), s2_valid, 1000) 421e39d6828Sxu_zh// assert(!(assert_valid && assert_val)) 42279b191f7SJay 423b92f8445Sssszwic /** 424b92f8445Sssszwic ****************************************************************************** 425b92f8445Sssszwic * monitor missUint response port 426b92f8445Sssszwic ****************************************************************************** 427b92f8445Sssszwic */ 428*415fcbe2Sxu_zh private val s2_MSHR_match = VecInit((0 until PortNumber).map { i => 429fa42eb78Sxu_zh (s2_req_vSetIdx(i) === fromMSHR.bits.vSetIdx) && 430b92f8445Sssszwic (s2_req_ptags(i) === getPhyTagFromBlk(fromMSHR.bits.blkPaddr)) && 431fa42eb78Sxu_zh fromMSHR.valid // we don't care about whether it's corrupt here 432*415fcbe2Sxu_zh }) 433*415fcbe2Sxu_zh private val s2_MSHR_hits = Seq(s2_valid && s2_MSHR_match(0), s2_valid && s2_MSHR_match(1) && s2_doubleline) 434*415fcbe2Sxu_zh private val s2_MSHR_datas = fromMSHR.bits.data.asTypeOf(Vec(ICacheDataBanks, UInt((blockBits / ICacheDataBanks).W))) 435b92f8445Sssszwic 436*415fcbe2Sxu_zh private val s2_bankIdxLow = (s2_req_offset >> log2Ceil(blockBytes / ICacheDataBanks)).asUInt 437*415fcbe2Sxu_zh private val s2_bankMSHRHit = VecInit((0 until ICacheDataBanks).map { i => 438fa42eb78Sxu_zh ((i.U >= s2_bankIdxLow) && s2_MSHR_hits(0)) || ((i.U < s2_bankIdxLow) && s2_MSHR_hits(1)) 439*415fcbe2Sxu_zh }) 440b92f8445Sssszwic 441b92f8445Sssszwic (0 until ICacheDataBanks).foreach { i => 442b92f8445Sssszwic when(s1_fire) { 443b92f8445Sssszwic s2_datas := s1_datas 444e39d6828Sxu_zh s2_data_is_from_MSHR := s1_data_is_from_MSHR 445e39d6828Sxu_zh }.elsewhen(s2_bankMSHRHit(i)) { 446b92f8445Sssszwic s2_datas(i) := s2_MSHR_datas(i) 447e39d6828Sxu_zh // also update s2_data_is_from_MSHR when re-fetched, to clear s2_data_corrupt flag and let s2_fire 448e39d6828Sxu_zh s2_data_is_from_MSHR(i) := true.B 449b92f8445Sssszwic } 450b92f8445Sssszwic } 451b92f8445Sssszwic 452b92f8445Sssszwic (0 until PortNumber).foreach { i => 453b92f8445Sssszwic when(s1_fire) { 454b92f8445Sssszwic s2_hits := s1_hits 455b92f8445Sssszwic }.elsewhen(s2_MSHR_hits(i)) { 456fa42eb78Sxu_zh // update s2_hits even if it's corrupt, to let s2_fire 457b92f8445Sssszwic s2_hits(i) := true.B 458e39d6828Sxu_zh // also clear s2_meta_corrupt flag when re-fetched, to let s2_fire 459e39d6828Sxu_zh s2_meta_corrupt(i) := false.B 460b92f8445Sssszwic } 461b92f8445Sssszwic } 462b92f8445Sssszwic 463*415fcbe2Sxu_zh private val s2_l2_corrupt = RegInit(VecInit(Seq.fill(PortNumber)(false.B))) 464b92f8445Sssszwic (0 until PortNumber).foreach { i => 465b92f8445Sssszwic when(s1_fire) { 46688895b11Sxu_zh s2_l2_corrupt(i) := false.B 467b92f8445Sssszwic }.elsewhen(s2_MSHR_hits(i)) { 46888895b11Sxu_zh s2_l2_corrupt(i) := fromMSHR.bits.corrupt 469b92f8445Sssszwic } 470b92f8445Sssszwic } 471b92f8445Sssszwic 472b92f8445Sssszwic /** 473b92f8445Sssszwic ****************************************************************************** 474e39d6828Sxu_zh * send request to MSHR if ICache miss / ECC corrupt 475b92f8445Sssszwic ****************************************************************************** 476b92f8445Sssszwic */ 477002c10a4SYanqin Li 478002c10a4SYanqin Li // merge pmp mmio and itlb pbmt 479*415fcbe2Sxu_zh private val s2_mmio = VecInit((s2_pmp_mmio zip s2_itlb_pbmt).map { case (mmio, pbmt) => 480002c10a4SYanqin Li mmio || Pbmt.isUncache(pbmt) 481002c10a4SYanqin Li }) 482002c10a4SYanqin Li 483e39d6828Sxu_zh // try re-fetch data from L2 cache if ECC error is detected, unless it's from MSHR 484*415fcbe2Sxu_zh private val s2_corrupt_refetch = (s2_meta_corrupt zip s2_data_corrupt).map { 485e39d6828Sxu_zh case (meta, data) => meta || data 486e39d6828Sxu_zh } 487e39d6828Sxu_zh 488f80535c3Sxu_zh /* s2_exception includes itlb pf/gpf/af, pmp af and meta corruption (af), neither of which should be fetched 489f80535c3Sxu_zh * mmio should not be fetched, it will be fetched by IFU mmio fsm 490f80535c3Sxu_zh * also, if previous has exception, latter port should also not be fetched 49188895b11Sxu_zh */ 492*415fcbe2Sxu_zh private val s2_should_fetch = VecInit((0 until PortNumber).map { i => 493e39d6828Sxu_zh (!s2_hits(i) || s2_corrupt_refetch(i)) && 494e39d6828Sxu_zh (if (i == 0) true.B else s2_doubleline) && 495dd02bc3fSxu_zh !ExceptionType.hasException(s2_exception.take(i + 1)) && 49688895b11Sxu_zh s2_mmio.take(i + 1).map(!_).reduce(_ && _) 497b808ac73Sxu_zh }) 498b92f8445Sssszwic 499*415fcbe2Sxu_zh private val toMSHRArbiter = Module(new Arbiter(new ICacheMissReq, PortNumber)) 500b92f8445Sssszwic 501b92f8445Sssszwic // To avoid sending duplicate requests. 502*415fcbe2Sxu_zh private val s2_has_send = RegInit(VecInit(Seq.fill(PortNumber)(false.B))) 503b92f8445Sssszwic (0 until PortNumber).foreach { i => 504b92f8445Sssszwic when(s1_fire) { 505e39d6828Sxu_zh s2_has_send(i) := false.B 506b92f8445Sssszwic }.elsewhen(toMSHRArbiter.io.in(i).fire) { 507e39d6828Sxu_zh s2_has_send(i) := true.B 508b92f8445Sssszwic } 509b92f8445Sssszwic } 510b92f8445Sssszwic 511*415fcbe2Sxu_zh (0 until PortNumber).foreach { i => 512e39d6828Sxu_zh toMSHRArbiter.io.in(i).valid := s2_valid && s2_should_fetch(i) && !s2_has_send(i) && !s2_flush 513b92f8445Sssszwic toMSHRArbiter.io.in(i).bits.blkPaddr := getBlkAddr(s2_req_paddr(i)) 514b92f8445Sssszwic toMSHRArbiter.io.in(i).bits.vSetIdx := s2_req_vSetIdx(i) 515b92f8445Sssszwic } 516b92f8445Sssszwic toMSHR <> toMSHRArbiter.io.out 517b92f8445Sssszwic 518b92f8445Sssszwic XSPerfAccumulate("to_missUnit_stall", toMSHR.valid && !toMSHR.ready) 519b92f8445Sssszwic 520*415fcbe2Sxu_zh private val s2_fetch_finish = !s2_should_fetch.reduce(_ || _) 521f80535c3Sxu_zh 522e39d6828Sxu_zh // also raise af if l2 corrupt is detected 523*415fcbe2Sxu_zh private val s2_l2_exception = VecInit(s2_l2_corrupt.map(ExceptionType.fromECC(true.B, _))) 524e39d6828Sxu_zh // NOTE: do NOT raise af if meta/data corrupt is detected, they are automatically recovered by re-fetching from L2 525f80535c3Sxu_zh 526e39d6828Sxu_zh // merge s2 exceptions, itlb has the highest priority, then l2 527*415fcbe2Sxu_zh private val s2_exception_out = ExceptionType.merge( 528e39d6828Sxu_zh s2_exception, // includes itlb/pmp exception 529f80535c3Sxu_zh s2_l2_exception 53088895b11Sxu_zh ) 531b92f8445Sssszwic 532b92f8445Sssszwic /** 533b92f8445Sssszwic ****************************************************************************** 534b92f8445Sssszwic * response to IFU 535b92f8445Sssszwic ****************************************************************************** 536b92f8445Sssszwic */ 5374690c88aSxu_zh toIFU.valid := s2_fire 5384690c88aSxu_zh toIFU.bits.doubleline := s2_doubleline 5394690c88aSxu_zh toIFU.bits.data := s2_datas.asTypeOf(UInt(blockBits.W)) 5404690c88aSxu_zh toIFU.bits.backendException := s2_backendException 5411a5af821Sxu_zh (0 until PortNumber).foreach { i => 5424690c88aSxu_zh toIFU.bits.vaddr(i) := s2_req_vaddr(i) 5434690c88aSxu_zh toIFU.bits.paddr(i) := s2_req_paddr(i) 5444690c88aSxu_zh val needThisLine = if (i == 0) true.B else s2_doubleline 5454690c88aSxu_zh toIFU.bits.exception(i) := Mux(needThisLine, s2_exception_out(i), ExceptionType.none) 5464690c88aSxu_zh toIFU.bits.pmp_mmio(i) := Mux(needThisLine, s2_pmp_mmio(i), false.B) 5474690c88aSxu_zh toIFU.bits.itlb_pbmt(i) := Mux(needThisLine, s2_itlb_pbmt(i), Pbmt.pma) 548b92f8445Sssszwic } 5494690c88aSxu_zh // valid only for the first gpf 5504690c88aSxu_zh toIFU.bits.gpaddr := s2_req_gpaddr 5514690c88aSxu_zh toIFU.bits.isForVSnonLeafPTE := s2_req_isForVSnonLeafPTE 552b92f8445Sssszwic 553b92f8445Sssszwic s2_flush := io.flush 554b92f8445Sssszwic s2_ready := (s2_fetch_finish && !io.respStall) || !s2_valid 555b92f8445Sssszwic s2_fire := s2_valid && s2_fetch_finish && !io.respStall && !s2_flush 556b92f8445Sssszwic 557b92f8445Sssszwic /** 558b92f8445Sssszwic ****************************************************************************** 559b92f8445Sssszwic * report Tilelink corrupt error 560b92f8445Sssszwic ****************************************************************************** 561b92f8445Sssszwic */ 562*415fcbe2Sxu_zh (0 until PortNumber).foreach { i => 56388895b11Sxu_zh when(RegNext(s2_fire && s2_l2_corrupt(i))) { 564a61a35e0Sssszwic io.errors(i).valid := true.B 5650184a80eSYanqin Li io.errors(i).bits.report_to_beu := false.B // l2 should have report that to bus error unit, no need to do it again 566b92f8445Sssszwic io.errors(i).bits.paddr := RegNext(s2_req_paddr(i)) 5670184a80eSYanqin Li io.errors(i).bits.source.tag := false.B 5680184a80eSYanqin Li io.errors(i).bits.source.data := false.B 5690184a80eSYanqin Li io.errors(i).bits.source.l2 := true.B 5701d8f4dcbSJay } 5711d8f4dcbSJay } 5721d8f4dcbSJay 573a61a35e0Sssszwic /** 574a61a35e0Sssszwic ****************************************************************************** 575a61a35e0Sssszwic * performance info. TODO: need to simplify the logic 576a61a35e0Sssszwic ***********************************************************s******************* 577a61a35e0Sssszwic */ 578b92f8445Sssszwic io.perfInfo.only_0_hit := s2_hits(0) && !s2_doubleline 579b92f8445Sssszwic io.perfInfo.only_0_miss := !s2_hits(0) && !s2_doubleline 580b92f8445Sssszwic io.perfInfo.hit_0_hit_1 := s2_hits(0) && s2_hits(1) && s2_doubleline 581b92f8445Sssszwic io.perfInfo.hit_0_miss_1 := s2_hits(0) && !s2_hits(1) && s2_doubleline 582b92f8445Sssszwic io.perfInfo.miss_0_hit_1 := !s2_hits(0) && s2_hits(1) && s2_doubleline 583b92f8445Sssszwic io.perfInfo.miss_0_miss_1 := !s2_hits(0) && !s2_hits(1) && s2_doubleline 584*415fcbe2Sxu_zh io.perfInfo.hit_0_except_1 := s2_hits(0) && ExceptionType.hasException(s2_exception(1)) && s2_doubleline 585*415fcbe2Sxu_zh io.perfInfo.miss_0_except_1 := !s2_hits(0) && ExceptionType.hasException(s2_exception(1)) && s2_doubleline 586b92f8445Sssszwic io.perfInfo.bank_hit(0) := s2_hits(0) 587b92f8445Sssszwic io.perfInfo.bank_hit(1) := s2_hits(1) && s2_doubleline 588dd02bc3fSxu_zh io.perfInfo.except_0 := ExceptionType.hasException(s2_exception(0)) 589b92f8445Sssszwic io.perfInfo.hit := s2_hits(0) && (!s2_doubleline || s2_hits(1)) 59058dbdfc2SJay 59158dbdfc2SJay /** <PERF> fetch bubble generated by icache miss */ 59200240ba6SJay XSPerfAccumulate("icache_bubble_s2_miss", s2_valid && !s2_fetch_finish) 593b92f8445Sssszwic XSPerfAccumulate("icache_bubble_s0_wayLookup", s0_valid && !fromWayLookup.ready) 594b92f8445Sssszwic 595b92f8445Sssszwic io.fetch.topdownIcacheMiss := !s2_fetch_finish 596b92f8445Sssszwic io.fetch.topdownItlbMiss := s0_valid && !fromWayLookup.ready 597b92f8445Sssszwic 598b92f8445Sssszwic // class ICacheTouchDB(implicit p: Parameters) extends ICacheBundle{ 599b92f8445Sssszwic // val blkPaddr = UInt((PAddrBits - blockOffBits).W) 600b92f8445Sssszwic // val vSetIdx = UInt(idxBits.W) 601*415fcbe2Sxu_zh // val waymask = UInt(wayBits.W) 602b92f8445Sssszwic // } 603b92f8445Sssszwic 604*415fcbe2Sxu_zh // private val isWriteICacheTouchTable = 605*415fcbe2Sxu_zh // WireInit(Constantin.createRecord("isWriteICacheTouchTable" + p(XSCoreParamsKey).HartId.toString)) 606*415fcbe2Sxu_zh // private val ICacheTouchTable = 607*415fcbe2Sxu_zh // ChiselDB.createTable("ICacheTouchTable" + p(XSCoreParamsKey).HartId.toString, new ICacheTouchDB) 608b92f8445Sssszwic 609b92f8445Sssszwic // val ICacheTouchDumpData = Wire(Vec(PortNumber, new ICacheTouchDB)) 610b92f8445Sssszwic // (0 until PortNumber).foreach{ i => 611b92f8445Sssszwic // ICacheTouchDumpData(i).blkPaddr := getBlkAddr(s2_req_paddr(i)) 612b92f8445Sssszwic // ICacheTouchDumpData(i).vSetIdx := s2_req_vSetIdx(i) 613b92f8445Sssszwic // ICacheTouchDumpData(i).waymask := OHToUInt(s2_tag_match_vec(i)) 614b92f8445Sssszwic // ICacheTouchTable.log( 615b92f8445Sssszwic // data = ICacheTouchDumpData(i), 616b92f8445Sssszwic // en = io.touch(i).valid, 617b92f8445Sssszwic // site = "req_" + i.toString, 618b92f8445Sssszwic // clock = clock, 619b92f8445Sssszwic // reset = reset 620b92f8445Sssszwic // ) 621b92f8445Sssszwic // } 62258dbdfc2SJay 623a61a35e0Sssszwic /** 624a61a35e0Sssszwic ****************************************************************************** 625a61a35e0Sssszwic * difftest refill check 626a61a35e0Sssszwic ****************************************************************************** 627a61a35e0Sssszwic */ 628afa866b1Sguohongyu if (env.EnableDifftest) { 629afa866b1Sguohongyu val discards = (0 until PortNumber).map { i => 6304690c88aSxu_zh ExceptionType.hasException(toIFU.bits.exception(i)) || 6314690c88aSxu_zh toIFU.bits.pmp_mmio(i) || 6324690c88aSxu_zh Pbmt.isUncache(toIFU.bits.itlb_pbmt(i)) 633afa866b1Sguohongyu } 634*415fcbe2Sxu_zh val blkPaddrAll = s2_req_paddr.map(addr => (addr(PAddrBits - 1, blockOffBits) << blockOffBits).asUInt) 635*415fcbe2Sxu_zh (0 until ICacheDataBanks).foreach { i => 636a0c65233SYinan Xu val diffMainPipeOut = DifftestModule(new DiffRefillEvent, dontCare = true) 6377d45a146SYinan Xu diffMainPipeOut.coreid := io.hartId 638b92f8445Sssszwic diffMainPipeOut.index := (3 + i).U 639b92f8445Sssszwic 640b92f8445Sssszwic val bankSel = getBankSel(s2_req_offset, s2_valid).reduce(_ | _) 641b92f8445Sssszwic val lineSel = getLineSel(s2_req_offset) 642b92f8445Sssszwic 643b92f8445Sssszwic diffMainPipeOut.valid := s2_fire && bankSel(i).asBool && Mux(lineSel(i), !discards(1), !discards(0)) 644cf7d6b7aSMuzi diffMainPipeOut.addr := Mux( 645cf7d6b7aSMuzi lineSel(i), 646*415fcbe2Sxu_zh blkPaddrAll(1) + (i.U << log2Ceil(blockBytes / ICacheDataBanks)).asUInt, 647*415fcbe2Sxu_zh blkPaddrAll(0) + (i.U << log2Ceil(blockBytes / ICacheDataBanks)).asUInt 648cf7d6b7aSMuzi ) 649b92f8445Sssszwic 650b92f8445Sssszwic diffMainPipeOut.data := s2_datas(i).asTypeOf(diffMainPipeOut.data) 651b92f8445Sssszwic diffMainPipeOut.idtfr := DontCare 652afa866b1Sguohongyu } 653afa866b1Sguohongyu } 6541d8f4dcbSJay} 655