1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* Copyright (c) 2020-2021 Peng Cheng Laboratory 4* 5* XiangShan is licensed under Mulan PSL v2. 6* You can use this software according to the terms and conditions of the Mulan PSL v2. 7* You may obtain a copy of Mulan PSL v2 at: 8* http://license.coscl.org.cn/MulanPSL2 9* 10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13* 14* See the Mulan PSL v2 for more details. 15***************************************************************************************/ 16 17package xiangshan.frontend.icache 18 19import org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import difftest._ 23import freechips.rocketchip.tilelink.ClientStates 24import xiangshan._ 25import xiangshan.cache.mmu._ 26import utils._ 27import utility._ 28import xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle} 29import xiangshan.frontend.{FtqICacheInfo, FtqToICacheRequestBundle} 30 31class ICacheMainPipeReq(implicit p: Parameters) extends ICacheBundle 32{ 33 val vaddr = UInt(VAddrBits.W) 34 def vSetIdx = get_idx(vaddr) 35} 36 37class ICacheMainPipeResp(implicit p: Parameters) extends ICacheBundle 38{ 39 val vaddr = UInt(VAddrBits.W) 40 // val registerData = UInt(blockBits.W) 41 // val sramData = UInt(blockBits.W) 42 // val select = Bool() 43 val data = UInt((blockBits).W) 44 val paddr = UInt(PAddrBits.W) 45 val gpaddr = UInt(GPAddrBits.W) 46 val tlbExcp = new Bundle{ 47 val pageFault = Bool() 48 val guestPageFault = Bool() 49 val accessFault = Bool() 50 val mmio = Bool() 51 } 52} 53 54class ICacheMainPipeBundle(implicit p: Parameters) extends ICacheBundle 55{ 56 val req = Flipped(Decoupled(new FtqToICacheRequestBundle)) 57 val resp = Vec(PortNumber, ValidIO(new ICacheMainPipeResp)) 58 val topdownIcacheMiss = Output(Bool()) 59 val topdownItlbMiss = Output(Bool()) 60} 61 62class ICacheMetaReqBundle(implicit p: Parameters) extends ICacheBundle{ 63 val toIMeta = DecoupledIO(new ICacheReadBundle) 64 val fromIMeta = Input(new ICacheMetaRespBundle) 65} 66 67class ICacheDataReqBundle(implicit p: Parameters) extends ICacheBundle{ 68 val toIData = Vec(partWayNum, DecoupledIO(new ICacheReadBundle)) 69 val fromIData = Input(new ICacheDataRespBundle) 70} 71 72class ICacheMSHRBundle(implicit p: Parameters) extends ICacheBundle{ 73 val req = Decoupled(new ICacheMissReq) 74 val resp = Flipped(ValidIO(new ICacheMissResp)) 75} 76 77class ICachePMPBundle(implicit p: Parameters) extends ICacheBundle{ 78 val req = Valid(new PMPReqBundle()) 79 val resp = Input(new PMPRespBundle()) 80} 81 82class ICachePerfInfo(implicit p: Parameters) extends ICacheBundle{ 83 val only_0_hit = Bool() 84 val only_0_miss = Bool() 85 val hit_0_hit_1 = Bool() 86 val hit_0_miss_1 = Bool() 87 val miss_0_hit_1 = Bool() 88 val miss_0_miss_1 = Bool() 89 val hit_0_except_1 = Bool() 90 val miss_0_except_1 = Bool() 91 val except_0 = Bool() 92 val bank_hit = Vec(2,Bool()) 93 val hit = Bool() 94} 95 96class ICacheMainPipeInterface(implicit p: Parameters) extends ICacheBundle { 97 val hartId = Input(UInt(hartIdLen.W)) 98 /*** internal interface ***/ 99 val dataArray = new ICacheDataReqBundle 100 /** prefetch io */ 101 val touch = Vec(PortNumber,ValidIO(new ReplacerTouch)) 102 val wayLookupRead = Flipped(DecoupledIO(new WayLookupInfo)) 103 104 val mshr = new ICacheMSHRBundle 105 val errors = Output(Vec(PortNumber, ValidIO(new L1CacheErrorInfo))) 106 /*** outside interface ***/ 107 //val fetch = Vec(PortNumber, new ICacheMainPipeBundle) 108 /* when ftq.valid is high in T + 1 cycle 109 * the ftq component must be valid in T cycle 110 */ 111 val fetch = new ICacheMainPipeBundle 112 val pmp = Vec(PortNumber, new ICachePMPBundle) 113 val respStall = Input(Bool()) 114 115 val csr_parity_enable = Input(Bool()) 116 val flush = Input(Bool()) 117 118 val perfInfo = Output(new ICachePerfInfo) 119} 120 121class ICacheDB(implicit p: Parameters) extends ICacheBundle { 122 val blk_vaddr = UInt((VAddrBits - blockOffBits).W) 123 val blk_paddr = UInt((PAddrBits - blockOffBits).W) 124 val hit = Bool() 125} 126 127class ICacheMainPipe(implicit p: Parameters) extends ICacheModule 128{ 129 val io = IO(new ICacheMainPipeInterface) 130 131 /** Input/Output port */ 132 val (fromFtq, toIFU) = (io.fetch.req, io.fetch.resp) 133 val (toData, fromData) = (io.dataArray.toIData, io.dataArray.fromIData) 134 val (toMSHR, fromMSHR) = (io.mshr.req, io.mshr.resp) 135 val (toPMP, fromPMP) = (io.pmp.map(_.req), io.pmp.map(_.resp)) 136 val fromWayLookup = io.wayLookupRead 137 138 // Statistics on the frequency distribution of FTQ fire interval 139 val cntFtqFireInterval = RegInit(0.U(32.W)) 140 cntFtqFireInterval := Mux(fromFtq.fire, 1.U, cntFtqFireInterval + 1.U) 141 XSPerfHistogram("ftq2icache_fire", 142 cntFtqFireInterval, fromFtq.fire, 143 1, 300, 1, right_strict = true) 144 145 /** pipeline control signal */ 146 val s1_ready, s2_ready = Wire(Bool()) 147 val s0_fire, s1_fire , s2_fire = Wire(Bool()) 148 val s0_flush, s1_flush , s2_flush = Wire(Bool()) 149 150 /** 151 ****************************************************************************** 152 * ICache Stage 0 153 * - send req to data SRAM 154 * - get waymask and tlb info from wayLookup 155 ****************************************************************************** 156 */ 157 158 /** s0 control */ 159 // 0,1,2,3 -> dataArray(data); 4 -> mainPipe 160 // Ftq RegNext Register 161 val fromFtqReq = fromFtq.bits.pcMemRead 162 val s0_valid = fromFtq.valid 163 val s0_req_valid_all = (0 until partWayNum + 1).map(i => fromFtq.bits.readValid(i)) 164 val s0_req_vaddr_all = (0 until partWayNum + 1).map(i => VecInit(Seq(fromFtqReq(i).startAddr, fromFtqReq(i).nextlineStart))) 165 val s0_req_vSetIdx_all = (0 until partWayNum + 1).map(i => VecInit(s0_req_vaddr_all(i).map(get_idx(_)))) 166 val s0_req_offset_all = (0 until partWayNum + 1).map(i => s0_req_vaddr_all(i)(0)(log2Ceil(blockBytes)-1, 0)) 167 val s0_doubleline_all = (0 until partWayNum + 1).map(i => fromFtq.bits.readValid(i) && fromFtqReq(i).crossCacheline) 168 169 val s0_req_vaddr = s0_req_vaddr_all.last 170 val s0_req_vSetIdx = s0_req_vSetIdx_all.last 171 val s0_doubleline = s0_doubleline_all.last 172 173 /** 174 ****************************************************************************** 175 * get waymask and tlb info from wayLookup 176 ****************************************************************************** 177 */ 178 fromWayLookup.ready := s0_fire 179 val s0_waymasks = VecInit(fromWayLookup.bits.waymask.map(_.asTypeOf(Vec(nWays, Bool())))) 180 val s0_req_ptags = fromWayLookup.bits.ptag 181 val s0_req_gpaddr = fromWayLookup.bits.gpaddr 182 val s0_excp_tlb_af = fromWayLookup.bits.excp_tlb_af 183 val s0_excp_tlb_pf = fromWayLookup.bits.excp_tlb_pf 184 val s0_excp_tlb_gpf = fromWayLookup.bits.excp_tlb_gpf 185 val s0_meta_errors = fromWayLookup.bits.meta_errors 186 val s0_hits = VecInit((0 until PortNumber).map(i=> s0_waymasks(i).reduce(_||_))) 187 188 when(s0_fire){ 189 assert((0 until PortNumber).map(i => s0_req_vSetIdx(i) === fromWayLookup.bits.vSetIdx(i)).reduce(_&&_), 190 "vSetIdxs from ftq and wayLookup are different! vaddr0=0x%x ftq: vidx0=0x%x vidx1=0x%x wayLookup: vidx0=0x%x vidx1=0x%x", 191 s0_req_vaddr(0), s0_req_vSetIdx(0), s0_req_vSetIdx(1), fromWayLookup.bits.vSetIdx(0), fromWayLookup.bits.vSetIdx(1)) 192 } 193 194 /** 195 ****************************************************************************** 196 * data SRAM request 197 ****************************************************************************** 198 */ 199 for(i <- 0 until partWayNum) { 200 toData(i).valid := s0_req_valid_all(i) 201 toData(i).bits.isDoubleLine := s0_doubleline_all(i) 202 toData(i).bits.vSetIdx := s0_req_vSetIdx_all(i) 203 toData(i).bits.blkOffset := s0_req_offset_all(i) 204 toData(i).bits.wayMask := s0_waymasks 205 } 206 207 val s0_can_go = toData.last.ready && fromWayLookup.valid && s1_ready 208 s0_flush := io.flush 209 s0_fire := s0_valid && s0_can_go && !s0_flush 210 211 fromFtq.ready := s0_can_go 212 213 /** 214 ****************************************************************************** 215 * ICache Stage 1 216 * - PMP check 217 * - get Data SRAM read responses (latched for pipeline stop) 218 * - monitor missUint response port 219 ****************************************************************************** 220 */ 221 val s1_valid = generatePipeControl(lastFire = s0_fire, thisFire = s1_fire, thisFlush = s1_flush, lastFlush = false.B) 222 223 val s1_req_vaddr = RegEnable(s0_req_vaddr, 0.U.asTypeOf(s0_req_vaddr), s0_fire) 224 val s1_req_ptags = RegEnable(s0_req_ptags, 0.U.asTypeOf(s0_req_ptags), s0_fire) 225 val s1_req_gpaddr = RegEnable(s0_req_gpaddr, 0.U.asTypeOf(s0_req_gpaddr), s0_fire) 226 val s1_doubleline = RegEnable(s0_doubleline, 0.U.asTypeOf(s0_doubleline), s0_fire) 227 val s1_SRAMhits = RegEnable(s0_hits, 0.U.asTypeOf(s0_hits), s0_fire) 228 val s1_excp_tlb_af = RegEnable(s0_excp_tlb_af, 0.U.asTypeOf(s0_excp_tlb_af), s0_fire) 229 val s1_excp_tlb_pf = RegEnable(s0_excp_tlb_pf, 0.U.asTypeOf(s0_excp_tlb_pf), s0_fire) 230 val s1_excp_tlb_gpf = RegEnable(s0_excp_tlb_gpf, 0.U.asTypeOf(s0_excp_tlb_gpf), s0_fire) 231 val s1_waymasks = RegEnable(s0_waymasks, 0.U.asTypeOf(s0_waymasks), s0_fire) 232 val s1_meta_errors = RegEnable(s0_meta_errors, 0.U.asTypeOf(s0_meta_errors), s0_fire) 233 234 val s1_req_vSetIdx = s1_req_vaddr.map(get_idx(_)) 235 val s1_req_paddr = s1_req_vaddr.zip(s1_req_ptags).map{case(vaddr, ptag) => get_paddr_from_ptag(vaddr, ptag)} 236 val s1_req_offset = s1_req_vaddr(0)(log2Ceil(blockBytes)-1, 0) 237 238 /** 239 ****************************************************************************** 240 * update replacement status register 241 ****************************************************************************** 242 */ 243 (0 until PortNumber).foreach{ i => 244 io.touch(i).bits.vSetIdx := s1_req_vSetIdx(i) 245 io.touch(i).bits.way := OHToUInt(s1_waymasks(i)) 246 } 247 io.touch(0).valid := RegNext(s0_fire) && s1_SRAMhits(0) 248 io.touch(1).valid := RegNext(s0_fire) && s1_SRAMhits(1) && s1_doubleline 249 250 /** 251 ****************************************************************************** 252 * PMP check 253 ****************************************************************************** 254 */ 255 val pmpExcpAF = VecInit(Seq(fromPMP(0).instr, fromPMP(1).instr && s1_doubleline)) 256 val s1_excp_pmp_af = DataHoldBypass(pmpExcpAF, RegNext(s0_fire)) 257 // pmp port 258 toPMP.zipWithIndex.map { case (p, i) => 259 p.valid := s1_valid 260 p.bits.addr := s1_req_paddr(i) 261 p.bits.size := 3.U // TODO 262 p.bits.cmd := TlbCmd.exec 263 } 264 265 /** 266 ****************************************************************************** 267 * select data from MSHR, SRAM 268 ****************************************************************************** 269 */ 270 val s1_MSHR_match = VecInit((0 until PortNumber).map(i => (s1_req_vSetIdx(i) === fromMSHR.bits.vSetIdx) && 271 (s1_req_ptags(i) === getPhyTagFromBlk(fromMSHR.bits.blkPaddr)) && 272 fromMSHR.valid && !fromMSHR.bits.corrupt)) 273 val s1_MSHR_hits = Seq(s1_valid && s1_MSHR_match(0), 274 s1_valid && (s1_MSHR_match(1) && s1_doubleline)) 275 val s1_MSHR_datas = fromMSHR.bits.data.asTypeOf(Vec(ICacheDataBanks, UInt((blockBits/ICacheDataBanks).W))) 276 277 val s1_hits = (0 until PortNumber).map(i => ValidHoldBypass(s1_MSHR_hits(i) || (RegNext(s0_fire) && s1_SRAMhits(i)), s1_fire || s1_flush)) 278 279 val s1_bankIdxLow = s1_req_offset >> log2Ceil(blockBytes/ICacheDataBanks) 280 val s1_bankMSHRHit = VecInit((0 until ICacheDataBanks).map(i => (i.U >= s1_bankIdxLow) && s1_MSHR_hits(0) || 281 (i.U < s1_bankIdxLow) && s1_MSHR_hits(1))) 282 val s1_datas = VecInit((0 until ICacheDataBanks).map(i => DataHoldBypass(Mux(s1_bankMSHRHit(i), s1_MSHR_datas(i), fromData.datas(i)), 283 s1_bankMSHRHit(i) || RegNext(s0_fire)))) 284 val s1_codes = DataHoldBypass(fromData.codes, RegNext(s0_fire)) 285 286 s1_flush := io.flush 287 s1_ready := s2_ready || !s1_valid 288 s1_fire := s1_valid && s2_ready && !s1_flush 289 290 /** 291 ****************************************************************************** 292 * ICache Stage 2 293 * - send request to MSHR if ICache miss 294 * - monitor missUint response port 295 * - response to IFU 296 ****************************************************************************** 297 */ 298 299 val s2_valid = generatePipeControl(lastFire = s1_fire, thisFire = s2_fire, thisFlush = s2_flush, lastFlush = false.B) 300 301 val s2_req_vaddr = RegEnable(s1_req_vaddr, 0.U.asTypeOf(s1_req_vaddr), s1_fire) 302 val s2_req_ptags = RegEnable(s1_req_ptags, 0.U.asTypeOf(s1_req_ptags), s1_fire) 303 val s2_req_gpaddr = RegEnable(s1_req_gpaddr, 0.U.asTypeOf(s1_req_gpaddr), s0_fire) 304 val s2_doubleline = RegEnable(s1_doubleline, 0.U.asTypeOf(s1_doubleline), s1_fire) 305 val s2_excp_tlb_af = RegEnable(s1_excp_tlb_af, 0.U.asTypeOf(s1_excp_tlb_af), s1_fire) 306 val s2_excp_tlb_pf = RegEnable(s1_excp_tlb_pf, 0.U.asTypeOf(s1_excp_tlb_pf), s1_fire) 307 val s2_excp_tlb_gpf = RegEnable(s1_excp_tlb_gpf, 0.U.asTypeOf(s1_excp_tlb_gpf), s1_fire) 308 val s2_excp_pmp_af = RegEnable(VecInit(fromPMP.map(_.instr)), 0.U.asTypeOf(VecInit(fromPMP.map(_.instr))), s1_fire) 309 val s2_excp_pmp_mmio = RegEnable(VecInit(fromPMP.map(_.mmio)), 0.U.asTypeOf(VecInit(fromPMP.map(_.mmio))), s1_fire) 310 311 val s2_req_vSetIdx = s2_req_vaddr.map(get_idx(_)) 312 val s2_req_offset = s2_req_vaddr(0)(log2Ceil(blockBytes)-1, 0) 313 val s2_req_paddr = s2_req_vaddr.zip(s2_req_ptags).map{case(vaddr, ptag) => get_paddr_from_ptag(vaddr, ptag)} 314 315 val s2_SRAMhits = RegEnable(s1_SRAMhits, 0.U.asTypeOf(s1_SRAMhits), s1_fire) 316 val s2_codes = RegEnable(s1_codes, 0.U.asTypeOf(s1_codes), s1_fire) 317 val s2_hits = RegInit(VecInit(Seq.fill(PortNumber)(false.B))) 318 val s2_datas = RegInit(VecInit(Seq.fill(ICacheDataBanks)(0.U((blockBits/ICacheDataBanks).W)))) 319 320 /** 321 ****************************************************************************** 322 * report data parity error 323 ****************************************************************************** 324 */ 325 // check data error 326 val s2_bankSel = getBankSel(s2_req_offset, s2_valid) 327 val s2_bank_errors = (0 until ICacheDataBanks).map(i => (encode(s2_datas(i)) =/= s2_codes(i))) 328 val s2_data_errors = (0 until PortNumber).map(port => (0 until ICacheDataBanks).map(bank => 329 s2_bank_errors(bank) && s2_bankSel(port)(bank).asBool).reduce(_||_) && s2_SRAMhits(port)) 330 // meta error is checked in prefetch pipeline 331 val s2_meta_errors = RegEnable(s1_meta_errors, 0.U.asTypeOf(s1_meta_errors), s1_fire) 332 // send errors to top 333 (0 until PortNumber).map{ i => 334 io.errors(i).valid := io.csr_parity_enable && RegNext(s1_fire) && (s2_meta_errors(i) || s2_data_errors(i)) 335 io.errors(i).bits.report_to_beu := io.csr_parity_enable && RegNext(s1_fire) && (s2_meta_errors(i) || s2_data_errors(i)) 336 io.errors(i).bits.paddr := s2_req_paddr(i) 337 io.errors(i).bits.source := DontCare 338 io.errors(i).bits.source.tag := s2_meta_errors(i) 339 io.errors(i).bits.source.data := s2_data_errors(i) 340 io.errors(i).bits.source.l2 := false.B 341 io.errors(i).bits.opType := DontCare 342 io.errors(i).bits.opType.fetch := true.B 343 } 344 345 /** 346 ****************************************************************************** 347 * monitor missUint response port 348 ****************************************************************************** 349 */ 350 val s2_MSHR_match = VecInit((0 until PortNumber).map(i => (s2_req_vSetIdx(i) === fromMSHR.bits.vSetIdx) && 351 (s2_req_ptags(i) === getPhyTagFromBlk(fromMSHR.bits.blkPaddr)) && 352 fromMSHR.valid && !fromMSHR.bits.corrupt)) 353 val s2_MSHR_hits = Seq(s2_valid && s2_MSHR_match(0), 354 s2_valid && (s2_MSHR_match(1) && s2_doubleline)) 355 val s2_MSHR_datas = fromMSHR.bits.data.asTypeOf(Vec(ICacheDataBanks, UInt((blockBits/ICacheDataBanks).W))) 356 357 val s2_bankIdxLow = s2_req_offset >> log2Ceil(blockBytes/ICacheDataBanks) 358 val s2_bankMSHRHit = VecInit((0 until ICacheDataBanks).map(i => (i.U >= s2_bankIdxLow) && s2_MSHR_hits(0) || 359 (i.U < s2_bankIdxLow) && s2_MSHR_hits(1))) 360 361 (0 until ICacheDataBanks).foreach{i => 362 when(s1_fire) { 363 s2_datas := s1_datas 364 }.elsewhen(s2_bankMSHRHit(i)) { 365 s2_datas(i) := s2_MSHR_datas(i) 366 } 367 } 368 369 (0 until PortNumber).foreach{i => 370 when(s1_fire) { 371 s2_hits := s1_hits 372 }.elsewhen(s2_MSHR_hits(i)) { 373 s2_hits(i) := true.B 374 } 375 } 376 377 val s2_corrupt = RegInit(VecInit(Seq.fill(PortNumber)(false.B))) 378 (0 until PortNumber).foreach{i => 379 when(s1_fire) { 380 s2_corrupt(i) := false.B 381 }.elsewhen(s2_MSHR_hits(i)) { 382 s2_corrupt(i) := fromMSHR.bits.corrupt 383 } 384 } 385 386 /** 387 ****************************************************************************** 388 * send request to MSHR if ICache miss 389 ****************************************************************************** 390 */ 391 val s2_excp_tlb = VecInit((0 until PortNumber).map(i => s2_excp_tlb_af(i) || s2_excp_tlb_pf(i) || s2_excp_tlb_gpf(i))) 392 val s2_miss = Wire(Vec(2, Bool())) 393 s2_miss(0) := !s2_hits(0) && !s2_excp_tlb(0) && !s2_excp_pmp_af(0) && !s2_excp_pmp_mmio(0) 394 s2_miss(1) := s2_doubleline && !s2_hits(1) && !s2_excp_tlb(0) && !s2_excp_tlb(1) && 395 !s2_excp_pmp_af(0) && !s2_excp_pmp_af(1) && !s2_excp_pmp_mmio(0) 396 397 val toMSHRArbiter = Module(new Arbiter(new ICacheMissReq, PortNumber)) 398 399 // To avoid sending duplicate requests. 400 val has_send = RegInit(VecInit(Seq.fill(PortNumber)(false.B))) 401 (0 until PortNumber).foreach{ i => 402 when(s1_fire) { 403 has_send(i) := false.B 404 }.elsewhen(toMSHRArbiter.io.in(i).fire) { 405 has_send(i) := true.B 406 } 407 } 408 409 (0 until PortNumber).map{ i => 410 toMSHRArbiter.io.in(i).valid := s2_valid && s2_miss(i) && !has_send(i) && !s2_flush 411 toMSHRArbiter.io.in(i).bits.blkPaddr := getBlkAddr(s2_req_paddr(i)) 412 toMSHRArbiter.io.in(i).bits.vSetIdx := s2_req_vSetIdx(i) 413 } 414 toMSHR <> toMSHRArbiter.io.out 415 416 XSPerfAccumulate("to_missUnit_stall", toMSHR.valid && !toMSHR.ready) 417 418 val s2_fetch_finish = !s2_miss.reduce(_||_) 419 420 /** 421 ****************************************************************************** 422 * response to IFU 423 ****************************************************************************** 424 */ 425 (0 until PortNumber).map{ i => 426 if(i == 0) { 427 toIFU(i).valid := s2_fire 428 toIFU(i).bits.tlbExcp.pageFault := s2_excp_tlb_pf(i) 429 toIFU(i).bits.tlbExcp.guestPageFault := s2_excp_tlb_gpf(i) 430 toIFU(i).bits.tlbExcp.accessFault := s2_excp_tlb_af(i) || s2_excp_pmp_af(i) || s2_corrupt(i) 431 toIFU(i).bits.tlbExcp.mmio := s2_excp_pmp_mmio(0) && !s2_excp_tlb(0) && !s2_excp_pmp_af(0) 432 toIFU(i).bits.data := s2_datas.asTypeOf(UInt(blockBits.W)) 433 } else { 434 toIFU(i).valid := s2_fire && s2_doubleline 435 toIFU(i).bits.tlbExcp.pageFault := s2_excp_tlb_pf(i) && s2_doubleline 436 toIFU(i).bits.tlbExcp.guestPageFault := s2_excp_tlb_gpf(i) && s2_doubleline 437 toIFU(i).bits.tlbExcp.accessFault := (s2_excp_tlb_af(i) || s2_excp_pmp_af(i) || s2_corrupt(i)) && s2_doubleline 438 toIFU(i).bits.tlbExcp.mmio := (s2_excp_pmp_mmio(0) && !s2_excp_tlb(0) && !s2_excp_pmp_af(0)) && s2_doubleline 439 toIFU(i).bits.data := DontCare 440 } 441 toIFU(i).bits.vaddr := s2_req_vaddr(i) 442 toIFU(i).bits.paddr := s2_req_paddr(i) 443 toIFU(i).bits.gpaddr := s2_req_gpaddr 444 } 445 446 s2_flush := io.flush 447 s2_ready := (s2_fetch_finish && !io.respStall) || !s2_valid 448 s2_fire := s2_valid && s2_fetch_finish && !io.respStall && !s2_flush 449 450 /** 451 ****************************************************************************** 452 * report Tilelink corrupt error 453 ****************************************************************************** 454 */ 455 (0 until PortNumber).map{ i => 456 when(RegNext(s2_fire && s2_corrupt(i))){ 457 io.errors(i).valid := true.B 458 io.errors(i).bits.report_to_beu := false.B // l2 should have report that to bus error unit, no need to do it again 459 io.errors(i).bits.paddr := RegNext(s2_req_paddr(i)) 460 io.errors(i).bits.source.tag := false.B 461 io.errors(i).bits.source.data := false.B 462 io.errors(i).bits.source.l2 := true.B 463 } 464 } 465 466 /** 467 ****************************************************************************** 468 * performance info. TODO: need to simplify the logic 469 ***********************************************************s******************* 470 */ 471 io.perfInfo.only_0_hit := s2_hits(0) && !s2_doubleline 472 io.perfInfo.only_0_miss := !s2_hits(0) && !s2_doubleline 473 io.perfInfo.hit_0_hit_1 := s2_hits(0) && s2_hits(1) && s2_doubleline 474 io.perfInfo.hit_0_miss_1 := s2_hits(0) && !s2_hits(1) && s2_doubleline 475 io.perfInfo.miss_0_hit_1 := !s2_hits(0) && s2_hits(1) && s2_doubleline 476 io.perfInfo.miss_0_miss_1 := !s2_hits(0) && !s2_hits(1) && s2_doubleline 477 io.perfInfo.hit_0_except_1 := s2_hits(0) && (s2_excp_tlb(1) || s2_excp_pmp_af(1)) && s2_doubleline 478 io.perfInfo.miss_0_except_1 := !s2_hits(0) && (s2_excp_tlb(1) || s2_excp_pmp_af(1)) && s2_doubleline 479 io.perfInfo.bank_hit(0) := s2_hits(0) 480 io.perfInfo.bank_hit(1) := s2_hits(1) && s2_doubleline 481 io.perfInfo.except_0 := s2_excp_tlb(0) || s2_excp_pmp_af(0) 482 io.perfInfo.hit := s2_hits(0) && (!s2_doubleline || s2_hits(1)) 483 484 /** <PERF> fetch bubble generated by icache miss */ 485 XSPerfAccumulate("icache_bubble_s2_miss", s2_valid && !s2_fetch_finish ) 486 XSPerfAccumulate("icache_bubble_s0_wayLookup", s0_valid && !fromWayLookup.ready) 487 488 io.fetch.topdownIcacheMiss := !s2_fetch_finish 489 io.fetch.topdownItlbMiss := s0_valid && !fromWayLookup.ready 490 491 // class ICacheTouchDB(implicit p: Parameters) extends ICacheBundle{ 492 // val blkPaddr = UInt((PAddrBits - blockOffBits).W) 493 // val vSetIdx = UInt(idxBits.W) 494 // val waymask = UInt(log2Ceil(nWays).W) 495 // } 496 497 // val isWriteICacheTouchTable = WireInit(Constantin.createRecord("isWriteICacheTouchTable" + p(XSCoreParamsKey).HartId.toString)) 498 // val ICacheTouchTable = ChiselDB.createTable("ICacheTouchTable" + p(XSCoreParamsKey).HartId.toString, new ICacheTouchDB) 499 500 // val ICacheTouchDumpData = Wire(Vec(PortNumber, new ICacheTouchDB)) 501 // (0 until PortNumber).foreach{ i => 502 // ICacheTouchDumpData(i).blkPaddr := getBlkAddr(s2_req_paddr(i)) 503 // ICacheTouchDumpData(i).vSetIdx := s2_req_vSetIdx(i) 504 // ICacheTouchDumpData(i).waymask := OHToUInt(s2_tag_match_vec(i)) 505 // ICacheTouchTable.log( 506 // data = ICacheTouchDumpData(i), 507 // en = io.touch(i).valid, 508 // site = "req_" + i.toString, 509 // clock = clock, 510 // reset = reset 511 // ) 512 // } 513 514 /** 515 ****************************************************************************** 516 * difftest refill check 517 ****************************************************************************** 518 */ 519 if (env.EnableDifftest) { 520 val discards = (0 until PortNumber).map { i => 521 val discard = toIFU(i).bits.tlbExcp.pageFault || toIFU(i).bits.tlbExcp.guestPageFault || toIFU(i).bits.tlbExcp.accessFault || toIFU(i).bits.tlbExcp.mmio 522 discard 523 } 524 val blkPaddrAll = s2_req_paddr.map(addr => addr(PAddrBits - 1, blockOffBits) << blockOffBits) 525 (0 until ICacheDataBanks).map { i => 526 val diffMainPipeOut = DifftestModule(new DiffRefillEvent, dontCare = true) 527 diffMainPipeOut.coreid := io.hartId 528 diffMainPipeOut.index := (3 + i).U 529 530 val bankSel = getBankSel(s2_req_offset, s2_valid).reduce(_|_) 531 val lineSel = getLineSel(s2_req_offset) 532 533 diffMainPipeOut.valid := s2_fire && bankSel(i).asBool && Mux(lineSel(i), !discards(1), !discards(0)) 534 diffMainPipeOut.addr := Mux(lineSel(i), blkPaddrAll(1) + (i.U << (log2Ceil(blockBytes/ICacheDataBanks))), 535 blkPaddrAll(0) + (i.U << (log2Ceil(blockBytes/ICacheDataBanks)))) 536 537 diffMainPipeOut.data := s2_datas(i).asTypeOf(diffMainPipeOut.data) 538 diffMainPipeOut.idtfr := DontCare 539 } 540 } 541}