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._ 227d45a146SYinan Xuimport difftest._ 23cf7d6b7aSMuziimport org.chipsalliance.cde.config.Parameters 243c02ee8fSwakafaimport utility._ 25cf7d6b7aSMuziimport xiangshan._ 26cf7d6b7aSMuziimport xiangshan.backend.fu.PMPReqBundle 27cf7d6b7aSMuziimport xiangshan.backend.fu.PMPRespBundle 28cf7d6b7aSMuziimport xiangshan.cache.mmu._ 29cf7d6b7aSMuziimport xiangshan.frontend.ExceptionType 30cf7d6b7aSMuziimport xiangshan.frontend.FtqToICacheRequestBundle 311d8f4dcbSJay 32cf7d6b7aSMuziclass ICacheMainPipeResp(implicit p: Parameters) extends ICacheBundle { 33415fcbe2Sxu_zh val doubleline: Bool = Bool() 34415fcbe2Sxu_zh val vaddr: Vec[UInt] = Vec(PortNumber, UInt(VAddrBits.W)) 35415fcbe2Sxu_zh val data: UInt = UInt(blockBits.W) 36415fcbe2Sxu_zh val paddr: Vec[UInt] = Vec(PortNumber, UInt(PAddrBits.W)) 37415fcbe2Sxu_zh val exception: Vec[UInt] = Vec(PortNumber, UInt(ExceptionType.width.W)) 38415fcbe2Sxu_zh val pmp_mmio: Vec[Bool] = Vec(PortNumber, Bool()) 39415fcbe2Sxu_zh val itlb_pbmt: Vec[UInt] = Vec(PortNumber, UInt(Pbmt.width.W)) 40415fcbe2Sxu_zh val backendException: Bool = Bool() 41dd980d61SXu, Zefan /* NOTE: GPAddrBits(=50bit) is not enough for gpaddr here, refer to PR#3795 42dd980d61SXu, Zefan * Sv48*4 only allows 50bit gpaddr, when software violates this requirement 43dd980d61SXu, Zefan * it needs to fill the mtval2 register with the full XLEN(=64bit) gpaddr, 44dd980d61SXu, Zefan * PAddrBitsMax(=56bit currently) is required for the frontend datapath due to the itlb ppn length limitation 45dd980d61SXu, Zefan * (cases 56<x<=64 are handled by the backend datapath) 46dd980d61SXu, Zefan */ 47415fcbe2Sxu_zh val gpaddr: UInt = UInt(PAddrBitsMax.W) 48415fcbe2Sxu_zh val isForVSnonLeafPTE: Bool = Bool() 491d8f4dcbSJay} 501d8f4dcbSJay 51cf7d6b7aSMuziclass ICacheMainPipeBundle(implicit p: Parameters) extends ICacheBundle { 52415fcbe2Sxu_zh val req: DecoupledIO[FtqToICacheRequestBundle] = Flipped(DecoupledIO(new FtqToICacheRequestBundle)) 53415fcbe2Sxu_zh val resp: Valid[ICacheMainPipeResp] = ValidIO(new ICacheMainPipeResp) 54415fcbe2Sxu_zh val topdownIcacheMiss: Bool = Output(Bool()) 55415fcbe2Sxu_zh val topdownItlbMiss: Bool = Output(Bool()) 561d8f4dcbSJay} 571d8f4dcbSJay 581d8f4dcbSJayclass ICacheMetaReqBundle(implicit p: Parameters) extends ICacheBundle { 59415fcbe2Sxu_zh val toIMeta: DecoupledIO[ICacheReadBundle] = DecoupledIO(new ICacheReadBundle) 60415fcbe2Sxu_zh val fromIMeta: ICacheMetaRespBundle = Input(new ICacheMetaRespBundle) 611d8f4dcbSJay} 621d8f4dcbSJay 631d8f4dcbSJayclass ICacheDataReqBundle(implicit p: Parameters) extends ICacheBundle { 64415fcbe2Sxu_zh val toIData: Vec[DecoupledIO[ICacheReadBundle]] = Vec(partWayNum, DecoupledIO(new ICacheReadBundle)) 65415fcbe2Sxu_zh val fromIData: ICacheDataRespBundle = Input(new ICacheDataRespBundle) 661d8f4dcbSJay} 671d8f4dcbSJay 681d8f4dcbSJayclass ICacheMSHRBundle(implicit p: Parameters) extends ICacheBundle { 69415fcbe2Sxu_zh val req: DecoupledIO[ICacheMissReq] = DecoupledIO(new ICacheMissReq) 70415fcbe2Sxu_zh val resp: Valid[ICacheMissResp] = Flipped(ValidIO(new ICacheMissResp)) 711d8f4dcbSJay} 721d8f4dcbSJay 731d8f4dcbSJayclass ICachePMPBundle(implicit p: Parameters) extends ICacheBundle { 74415fcbe2Sxu_zh val req: Valid[PMPReqBundle] = ValidIO(new PMPReqBundle()) 75415fcbe2Sxu_zh val resp: PMPRespBundle = Input(new PMPRespBundle()) 761d8f4dcbSJay} 771d8f4dcbSJay 781d8f4dcbSJayclass ICachePerfInfo(implicit p: Parameters) extends ICacheBundle { 79415fcbe2Sxu_zh val only_0_hit: Bool = Bool() 80415fcbe2Sxu_zh val only_0_miss: Bool = Bool() 81415fcbe2Sxu_zh val hit_0_hit_1: Bool = Bool() 82415fcbe2Sxu_zh val hit_0_miss_1: Bool = Bool() 83415fcbe2Sxu_zh val miss_0_hit_1: Bool = Bool() 84415fcbe2Sxu_zh val miss_0_miss_1: Bool = Bool() 85415fcbe2Sxu_zh val hit_0_except_1: Bool = Bool() 86415fcbe2Sxu_zh val miss_0_except_1: Bool = Bool() 87415fcbe2Sxu_zh val except_0: Bool = Bool() 88415fcbe2Sxu_zh val bank_hit: Vec[Bool] = Vec(PortNumber, Bool()) 89415fcbe2Sxu_zh val hit: Bool = Bool() 901d8f4dcbSJay} 911d8f4dcbSJay 921d8f4dcbSJayclass ICacheMainPipeInterface(implicit p: Parameters) extends ICacheBundle { 93415fcbe2Sxu_zh val hartId: UInt = Input(UInt(hartIdLen.W)) 94cf7d6b7aSMuzi 952a3050c2SJay /*** internal interface ***/ 96415fcbe2Sxu_zh val dataArray: ICacheDataReqBundle = new ICacheDataReqBundle 97415fcbe2Sxu_zh val metaArrayFlush: Vec[Valid[ICacheMetaFlushBundle]] = Vec(PortNumber, ValidIO(new ICacheMetaFlushBundle)) 98415fcbe2Sxu_zh val touch: Vec[Valid[ReplacerTouch]] = Vec(PortNumber, ValidIO(new ReplacerTouch)) 99415fcbe2Sxu_zh val wayLookupRead: DecoupledIO[WayLookupInfo] = Flipped(DecoupledIO(new WayLookupInfo)) 100415fcbe2Sxu_zh val mshr: ICacheMSHRBundle = new ICacheMSHRBundle 1016c106319Sxu_zh val ecc_enable: Bool = Input(Bool()) 102cf7d6b7aSMuzi 1032a3050c2SJay /*** outside interface ***/ 104415fcbe2Sxu_zh // FTQ 105415fcbe2Sxu_zh val fetch: ICacheMainPipeBundle = new ICacheMainPipeBundle 106415fcbe2Sxu_zh val flush: Bool = Input(Bool()) 107415fcbe2Sxu_zh // PMP 108415fcbe2Sxu_zh val pmp: Vec[ICachePMPBundle] = Vec(PortNumber, new ICachePMPBundle) 109415fcbe2Sxu_zh // IFU 110415fcbe2Sxu_zh val respStall: Bool = Input(Bool()) 111415fcbe2Sxu_zh // backend/BEU 112415fcbe2Sxu_zh val errors: Vec[Valid[L1CacheErrorInfo]] = Output(Vec(PortNumber, ValidIO(new L1CacheErrorInfo))) 11358dbdfc2SJay 114415fcbe2Sxu_zh /*** PERF ***/ 115415fcbe2Sxu_zh val perfInfo: ICachePerfInfo = Output(new ICachePerfInfo) 1161d8f4dcbSJay} 1171d8f4dcbSJay 118415fcbe2Sxu_zh//class ICacheDB(implicit p: Parameters) extends ICacheBundle { 119415fcbe2Sxu_zh// val blk_vaddr: UInt = UInt((VAddrBits - blockOffBits).W) 120415fcbe2Sxu_zh// val blk_paddr: UInt = UInt((PAddrBits - blockOffBits).W) 121415fcbe2Sxu_zh// val hit: Bool = Bool() 122415fcbe2Sxu_zh//} 123f9c51548Sssszwic 1246c106319Sxu_zhclass ICacheMainPipe(implicit p: Parameters) extends ICacheModule with HasICacheECCHelper { 125415fcbe2Sxu_zh val io: ICacheMainPipeInterface = IO(new ICacheMainPipeInterface) 1261d8f4dcbSJay 12758dbdfc2SJay /** Input/Output port */ 128415fcbe2Sxu_zh private val (fromFtq, toIFU) = (io.fetch.req, io.fetch.resp) 129415fcbe2Sxu_zh private val (toData, fromData) = (io.dataArray.toIData, io.dataArray.fromIData) 130415fcbe2Sxu_zh private val toMetaFlush = io.metaArrayFlush 131415fcbe2Sxu_zh private val (toMSHR, fromMSHR) = (io.mshr.req, io.mshr.resp) 132415fcbe2Sxu_zh private val (toPMP, fromPMP) = (io.pmp.map(_.req), io.pmp.map(_.resp)) 133415fcbe2Sxu_zh private val fromWayLookup = io.wayLookupRead 1346c106319Sxu_zh private val ecc_enable = 1356c106319Sxu_zh if (ICacheForceMetaECCError || ICacheForceDataECCError) true.B else io.ecc_enable 13658c354d0Sssszwic 13758c354d0Sssszwic // Statistics on the frequency distribution of FTQ fire interval 138415fcbe2Sxu_zh private val cntFtqFireInterval = RegInit(0.U(32.W)) 139415fcbe2Sxu_zh private val cntFtqFireIntervalStart = 1 140415fcbe2Sxu_zh private val cntFtqFireIntervalEnd = 300 14158c354d0Sssszwic cntFtqFireInterval := Mux(fromFtq.fire, 1.U, cntFtqFireInterval + 1.U) 142415fcbe2Sxu_zh XSPerfHistogram( 143415fcbe2Sxu_zh "ftq2icache_fire", 144415fcbe2Sxu_zh cntFtqFireInterval, 145415fcbe2Sxu_zh fromFtq.fire, 146415fcbe2Sxu_zh cntFtqFireIntervalStart, 147415fcbe2Sxu_zh cntFtqFireIntervalEnd, 148415fcbe2Sxu_zh right_strict = true 149415fcbe2Sxu_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 167415fcbe2Sxu_zh private val fromFtqReq = fromFtq.bits.pcMemRead 168415fcbe2Sxu_zh private val s0_valid = fromFtq.valid 169415fcbe2Sxu_zh private val s0_req_valid_all = (0 until partWayNum + 1).map(i => fromFtq.bits.readValid(i)) 170415fcbe2Sxu_zh private val s0_req_vaddr_all = 171cf7d6b7aSMuzi (0 until partWayNum + 1).map(i => VecInit(Seq(fromFtqReq(i).startAddr, fromFtqReq(i).nextlineStart))) 172415fcbe2Sxu_zh private val s0_req_vSetIdx_all = (0 until partWayNum + 1).map(i => VecInit(s0_req_vaddr_all(i).map(get_idx))) 173415fcbe2Sxu_zh private val s0_req_offset_all = (0 until partWayNum + 1).map(i => s0_req_vaddr_all(i)(0)(log2Ceil(blockBytes) - 1, 0)) 174415fcbe2Sxu_zh private val s0_doubleline_all = 175415fcbe2Sxu_zh (0 until partWayNum + 1).map(i => fromFtq.bits.readValid(i) && fromFtqReq(i).crossCacheline) 1761d8f4dcbSJay 177415fcbe2Sxu_zh private val s0_req_vaddr = s0_req_vaddr_all.last 178415fcbe2Sxu_zh private val s0_req_vSetIdx = s0_req_vSetIdx_all.last 179415fcbe2Sxu_zh private val s0_doubleline = s0_doubleline_all.last 18061e1db30SJay 181415fcbe2Sxu_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 189415fcbe2Sxu_zh private val s0_waymasks = VecInit(fromWayLookup.bits.waymask.map(_.asTypeOf(Vec(nWays, Bool())))) 190415fcbe2Sxu_zh private val s0_req_ptags = fromWayLookup.bits.ptag 191415fcbe2Sxu_zh private val s0_req_gpaddr = fromWayLookup.bits.gpaddr 192415fcbe2Sxu_zh private val s0_req_isForVSnonLeafPTE = fromWayLookup.bits.isForVSnonLeafPTE 193415fcbe2Sxu_zh private val s0_itlb_exception = fromWayLookup.bits.itlb_exception 194415fcbe2Sxu_zh private val s0_itlb_pbmt = fromWayLookup.bits.itlb_pbmt 195415fcbe2Sxu_zh private val s0_meta_codes = fromWayLookup.bits.meta_codes 196415fcbe2Sxu_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(_ && _), 201415fcbe2Sxu_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 */ 215415fcbe2Sxu_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) 220415fcbe2Sxu_zh toData(i).bits.waymask := s0_waymasks 221b92f8445Sssszwic } 222afed18b5SJenius 223415fcbe2Sxu_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 */ 237415fcbe2Sxu_zh private val s1_valid = 238415fcbe2Sxu_zh generatePipeControl(lastFire = s0_fire, thisFire = s1_fire, thisFlush = s1_flush, lastFlush = false.B) 2391d8f4dcbSJay 240415fcbe2Sxu_zh private val s1_req_vaddr = RegEnable(s0_req_vaddr, 0.U.asTypeOf(s0_req_vaddr), s0_fire) 241415fcbe2Sxu_zh private val s1_req_ptags = RegEnable(s0_req_ptags, 0.U.asTypeOf(s0_req_ptags), s0_fire) 242415fcbe2Sxu_zh private val s1_req_gpaddr = RegEnable(s0_req_gpaddr, 0.U.asTypeOf(s0_req_gpaddr), s0_fire) 243415fcbe2Sxu_zh private val s1_req_isForVSnonLeafPTE = 244415fcbe2Sxu_zh RegEnable(s0_req_isForVSnonLeafPTE, 0.U.asTypeOf(s0_req_isForVSnonLeafPTE), s0_fire) 245415fcbe2Sxu_zh private val s1_doubleline = RegEnable(s0_doubleline, 0.U.asTypeOf(s0_doubleline), s0_fire) 246415fcbe2Sxu_zh private val s1_SRAMhits = RegEnable(s0_hits, 0.U.asTypeOf(s0_hits), s0_fire) 247415fcbe2Sxu_zh private val s1_itlb_exception = RegEnable(s0_itlb_exception, 0.U.asTypeOf(s0_itlb_exception), s0_fire) 248415fcbe2Sxu_zh private val s1_backendException = RegEnable(s0_backendException, false.B, s0_fire) 249415fcbe2Sxu_zh private val s1_itlb_pbmt = RegEnable(s0_itlb_pbmt, 0.U.asTypeOf(s0_itlb_pbmt), s0_fire) 250415fcbe2Sxu_zh private val s1_waymasks = RegEnable(s0_waymasks, 0.U.asTypeOf(s0_waymasks), s0_fire) 251415fcbe2Sxu_zh private val s1_meta_codes = RegEnable(s0_meta_codes, 0.U.asTypeOf(s0_meta_codes), s0_fire) 2521d8f4dcbSJay 253415fcbe2Sxu_zh private val s1_req_vSetIdx = s1_req_vaddr.map(get_idx) 254415fcbe2Sxu_zh private val s1_req_paddr = getPaddrFromPtag(s1_req_vaddr, s1_req_ptags) 255415fcbe2Sxu_zh private val s1_req_offset = s1_req_vaddr(0)(log2Ceil(blockBytes) - 1, 0) 256b1ded4e8Sguohongyu 2578966a895Sxu_zh // do metaArray ECC check 258415fcbe2Sxu_zh private val s1_meta_corrupt = VecInit((s1_req_ptags zip s1_meta_codes zip s1_waymasks).map { 259415fcbe2Sxu_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 263415fcbe2Sxu_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 2666c106319Sxu_zh when(!ecc_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) => 288415fcbe2Sxu_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) 291415fcbe2Sxu_zh p.bits.size := 3.U 292a61a35e0Sssszwic p.bits.cmd := TlbCmd.exec 293a61a35e0Sssszwic } 294415fcbe2Sxu_zh private val s1_pmp_exception = VecInit(fromPMP.map(ExceptionType.fromPMPResp)) 295415fcbe2Sxu_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 298415fcbe2Sxu_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 */ 308415fcbe2Sxu_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 312415fcbe2Sxu_zh }) 313415fcbe2Sxu_zh private val s1_MSHR_hits = Seq(s1_valid && s1_MSHR_match(0), s1_valid && (s1_MSHR_match(1) && s1_doubleline)) 314415fcbe2Sxu_zh private val s1_MSHR_datas = fromMSHR.bits.data.asTypeOf(Vec(ICacheDataBanks, UInt((blockBits / ICacheDataBanks).W))) 31579b191f7SJay 316415fcbe2Sxu_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) 318415fcbe2Sxu_zh } 319a61a35e0Sssszwic 320415fcbe2Sxu_zh private val s1_bankIdxLow = (s1_req_offset >> log2Ceil(blockBytes / ICacheDataBanks)).asUInt 321415fcbe2Sxu_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) 324415fcbe2Sxu_zh }) 325415fcbe2Sxu_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)) 327415fcbe2Sxu_zh }) 328415fcbe2Sxu_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)) 330415fcbe2Sxu_zh }) 331415fcbe2Sxu_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 346415fcbe2Sxu_zh private val s2_valid = 347415fcbe2Sxu_zh generatePipeControl(lastFire = s1_fire, thisFire = s2_fire, thisFlush = s2_flush, lastFlush = false.B) 348a61a35e0Sssszwic 349415fcbe2Sxu_zh private val s2_req_vaddr = RegEnable(s1_req_vaddr, 0.U.asTypeOf(s1_req_vaddr), s1_fire) 350415fcbe2Sxu_zh private val s2_req_ptags = RegEnable(s1_req_ptags, 0.U.asTypeOf(s1_req_ptags), s1_fire) 351415fcbe2Sxu_zh private val s2_req_gpaddr = RegEnable(s1_req_gpaddr, 0.U.asTypeOf(s1_req_gpaddr), s1_fire) 352415fcbe2Sxu_zh private val s2_req_isForVSnonLeafPTE = 353415fcbe2Sxu_zh RegEnable(s1_req_isForVSnonLeafPTE, 0.U.asTypeOf(s1_req_isForVSnonLeafPTE), s1_fire) 354415fcbe2Sxu_zh private val s2_doubleline = RegEnable(s1_doubleline, 0.U.asTypeOf(s1_doubleline), s1_fire) 355415fcbe2Sxu_zh private val s2_exception = RegEnable(s1_exception_out, 0.U.asTypeOf(s1_exception_out), s1_fire) 356415fcbe2Sxu_zh private val s2_backendException = RegEnable(s1_backendException, false.B, s1_fire) 357415fcbe2Sxu_zh private val s2_pmp_mmio = RegEnable(s1_pmp_mmio, 0.U.asTypeOf(s1_pmp_mmio), s1_fire) 358415fcbe2Sxu_zh private val s2_itlb_pbmt = RegEnable(s1_itlb_pbmt, 0.U.asTypeOf(s1_itlb_pbmt), s1_fire) 359415fcbe2Sxu_zh private val s2_waymasks = RegEnable(s1_waymasks, 0.U.asTypeOf(s1_waymasks), s1_fire) 360a61a35e0Sssszwic 361415fcbe2Sxu_zh private val s2_req_vSetIdx = s2_req_vaddr.map(get_idx) 362415fcbe2Sxu_zh private val s2_req_offset = s2_req_vaddr(0)(log2Ceil(blockBytes) - 1, 0) 363415fcbe2Sxu_zh private val s2_req_paddr = getPaddrFromPtag(s2_req_vaddr, s2_req_ptags) 364a61a35e0Sssszwic 365415fcbe2Sxu_zh private val s2_SRAMhits = RegEnable(s1_SRAMhits, 0.U.asTypeOf(s1_SRAMhits), s1_fire) 366415fcbe2Sxu_zh private val s2_codes = RegEnable(s1_codes, 0.U.asTypeOf(s1_codes), s1_fire) 367415fcbe2Sxu_zh private val s2_hits = RegInit(VecInit(Seq.fill(PortNumber)(false.B))) 368415fcbe2Sxu_zh private val s2_datas = RegInit(VecInit(Seq.fill(ICacheDataBanks)(0.U((blockBits / ICacheDataBanks).W)))) 369415fcbe2Sxu_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 377415fcbe2Sxu_zh private val s2_bankSel = getBankSel(s2_req_offset, s2_valid) 378415fcbe2Sxu_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 380415fcbe2Sxu_zh private val s2_data_corrupt = VecInit((0 until PortNumber).map { port => 381415fcbe2Sxu_zh (0 until ICacheDataBanks).map { bank => 382e39d6828Sxu_zh s2_bank_corrupt(bank) && s2_bankSel(port)(bank).asBool && !s2_data_is_from_MSHR(bank) 383415fcbe2Sxu_zh }.reduce(_ || _) && s2_SRAMhits(port) 384415fcbe2Sxu_zh }) 385e39d6828Sxu_zh // force clear data_corrupt when parity check is disabled 3866c106319Sxu_zh when(!ecc_enable) { 387e39d6828Sxu_zh s2_data_corrupt := VecInit(Seq.fill(PortNumber)(false.B)) 388e39d6828Sxu_zh } 389e39d6828Sxu_zh // meta error is checked in s1 stage 390415fcbe2Sxu_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 393415fcbe2Sxu_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 */ 428415fcbe2Sxu_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 432415fcbe2Sxu_zh }) 433415fcbe2Sxu_zh private val s2_MSHR_hits = Seq(s2_valid && s2_MSHR_match(0), s2_valid && s2_MSHR_match(1) && s2_doubleline) 434415fcbe2Sxu_zh private val s2_MSHR_datas = fromMSHR.bits.data.asTypeOf(Vec(ICacheDataBanks, UInt((blockBits / ICacheDataBanks).W))) 435b92f8445Sssszwic 436415fcbe2Sxu_zh private val s2_bankIdxLow = (s2_req_offset >> log2Ceil(blockBytes / ICacheDataBanks)).asUInt 437415fcbe2Sxu_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)) 439415fcbe2Sxu_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 463415fcbe2Sxu_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 479415fcbe2Sxu_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 484415fcbe2Sxu_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 */ 492415fcbe2Sxu_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 499415fcbe2Sxu_zh private val toMSHRArbiter = Module(new Arbiter(new ICacheMissReq, PortNumber)) 500b92f8445Sssszwic 501b92f8445Sssszwic // To avoid sending duplicate requests. 502415fcbe2Sxu_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 511415fcbe2Sxu_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 520415fcbe2Sxu_zh private val s2_fetch_finish = !s2_should_fetch.reduce(_ || _) 521f80535c3Sxu_zh 522e39d6828Sxu_zh // also raise af if l2 corrupt is detected 523*dfb03ba2Sxu_zh private val s2_l2_exception = VecInit(s2_l2_corrupt.map(ExceptionType.fromTilelink)) 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 527415fcbe2Sxu_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 */ 562415fcbe2Sxu_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 584415fcbe2Sxu_zh io.perfInfo.hit_0_except_1 := s2_hits(0) && ExceptionType.hasException(s2_exception(1)) && s2_doubleline 585415fcbe2Sxu_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) 601415fcbe2Sxu_zh // val waymask = UInt(wayBits.W) 602b92f8445Sssszwic // } 603b92f8445Sssszwic 604415fcbe2Sxu_zh // private val isWriteICacheTouchTable = 605415fcbe2Sxu_zh // WireInit(Constantin.createRecord("isWriteICacheTouchTable" + p(XSCoreParamsKey).HartId.toString)) 606415fcbe2Sxu_zh // private val ICacheTouchTable = 607415fcbe2Sxu_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 } 634415fcbe2Sxu_zh val blkPaddrAll = s2_req_paddr.map(addr => (addr(PAddrBits - 1, blockOffBits) << blockOffBits).asUInt) 635415fcbe2Sxu_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), 646415fcbe2Sxu_zh blkPaddrAll(1) + (i.U << log2Ceil(blockBytes / ICacheDataBanks)).asUInt, 647415fcbe2Sxu_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