1/*************************************************************************************** 2 * Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 3 * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 4 * Copyright (c) 2020-2021 Peng Cheng Laboratory 5 * 6 * XiangShan is licensed under Mulan PSL v2. 7 * You can use this software according to the terms and conditions of the Mulan PSL v2. 8 * You may obtain a copy of Mulan PSL v2 at: 9 * http://license.coscl.org.cn/MulanPSL2 10 * 11 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 12 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 13 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 14 * 15 * See the Mulan PSL v2 for more details. 16 ***************************************************************************************/ 17package xiangshan.mem 18 19import org.chipsalliance.cde.config._ 20import chisel3._ 21import chisel3.util._ 22import utils._ 23import utility._ 24import xiangshan._ 25import xiangshan.ExceptionNO._ 26import xiangshan.backend.rob.{RobPtr, RobLsqIO} 27import xiangshan.backend.Bundles 28import xiangshan.backend.Bundles.{DynInst, MemExuOutput} 29import xiangshan.backend.fu.FuConfig.LduCfg 30import xiangshan.mem.Bundles._ 31import xiangshan.cache._ 32 33class UncacheEntry(entryIndex: Int)(implicit p: Parameters) extends XSModule 34 with HasCircularQueuePtrHelper 35 with HasLoadHelper 36{ 37 val io = IO(new Bundle() { 38 /* control */ 39 val redirect = Flipped(Valid(new Redirect)) 40 // redirect flush 41 val flush = Output(Bool()) 42 // mmio commit 43 val rob = Flipped(new RobLsqIO) 44 // mmio select 45 val mmioSelect = Output(Bool()) 46 // slaveId 47 val slaveId = ValidIO(UInt(UncacheBufferIndexWidth.W)) 48 49 /* transaction */ 50 // from ldu 51 val req = Flipped(Valid(new LqWriteBundle)) 52 // to ldu: mmio, data 53 val mmioOut = DecoupledIO(new MemExuOutput) 54 val mmioRawData = Output(new LoadDataFromLQBundle) 55 // to ldu: nc with data 56 val ncOut = DecoupledIO(new LsPipelineBundle) 57 // <=> uncache 58 val uncache = new UncacheWordIO 59 // exception generated by outer bus 60 val exception = Valid(new LqWriteBundle) 61 }) 62 63 val req_valid = RegInit(false.B) 64 val req = Reg(new LqWriteBundle) 65 val slaveAccept = RegInit(false.B) 66 val slaveId = Reg(UInt(UncacheBufferIndexWidth.W)) 67 68 val s_idle :: s_req :: s_resp :: s_wait :: Nil = Enum(4) 69 val uncacheState = RegInit(s_idle) 70 val uncacheData = Reg(io.uncache.resp.bits.data.cloneType) 71 val nderr = RegInit(false.B) 72 73 val writeback = Mux(req.nc, io.ncOut.fire, io.mmioOut.fire) 74 val slaveAck = req_valid && io.uncache.idResp.valid && io.uncache.idResp.bits.mid === entryIndex.U 75 76 /** 77 * Flush 78 * 79 * 1. direct flush during idle 80 * 2. otherwise delayed flush until receiving uncache resp 81 */ 82 val needFlushReg = RegInit(false.B) 83 val needFlush = req_valid && req.uop.robIdx.needFlush(io.redirect) 84 val flush = (needFlush && uncacheState===s_idle) || (io.uncache.resp.fire && needFlushReg) 85 when(flush){ 86 needFlushReg := false.B 87 }.elsewhen(needFlush){ 88 needFlushReg := true.B 89 } 90 91 /* enter req */ 92 when (flush) { 93 req_valid := false.B 94 slaveAccept := false.B 95 } .elsewhen (io.req.valid) { 96 req_valid := true.B 97 slaveAccept := false.B 98 req := io.req.bits 99 nderr := false.B 100 } .elsewhen(slaveAck) { 101 slaveAccept := true.B 102 slaveId := io.uncache.idResp.bits.sid 103 } .elsewhen (writeback) { 104 req_valid := false.B 105 slaveAccept := false.B 106 } 107 XSError(!flush && io.req.valid && req_valid, p"LoadQueueUncache: You can not write an valid entry: $entryIndex") 108 109 /** 110 * Memory mapped IO / NC operations 111 * 112 * States: 113 * (1) s_idle: wait for mmio reaching ROB's head / nc req valid from loadunit 114 * (2) s_req: wait to be sent to uncache channel until req selected and uncache ready 115 * (3) s_resp: wait for response from uncache channel 116 * (4) s_wait: wait for loadunit to receive writeback req 117 */ 118 val pendingld = GatedValidRegNext(io.rob.pendingMMIOld) 119 val pendingPtr = GatedRegNext(io.rob.pendingPtr) 120 val canSendReq = req_valid && !needFlush && Mux( 121 req.nc, true.B, 122 pendingld && req.uop.robIdx === pendingPtr 123 ) 124 switch (uncacheState) { 125 is (s_idle) { 126 when (canSendReq) { 127 uncacheState := s_req 128 } 129 } 130 is (s_req) { 131 when (io.uncache.req.fire) { 132 uncacheState := s_resp 133 } 134 } 135 is (s_resp) { 136 when (io.uncache.resp.fire) { 137 when (needFlushReg) { 138 uncacheState := s_idle 139 }.otherwise{ 140 uncacheState := s_wait 141 } 142 } 143 } 144 is (s_wait) { 145 when (writeback) { 146 uncacheState := s_idle 147 } 148 } 149 } 150 151 /* control */ 152 io.flush := flush 153 io.rob.mmio := DontCare 154 io.rob.uop := DontCare 155 io.mmioSelect := (uncacheState =/= s_idle) && req.mmio 156 io.slaveId.valid := slaveAccept 157 io.slaveId.bits := slaveId 158 159 /* uncahce req */ 160 io.uncache.req.valid := uncacheState === s_req 161 io.uncache.req.bits := DontCare 162 io.uncache.req.bits.cmd := MemoryOpConstants.M_XRD 163 io.uncache.req.bits.data := DontCare 164 io.uncache.req.bits.addr := req.paddr 165 io.uncache.req.bits.vaddr:= req.vaddr 166 io.uncache.req.bits.mask := Mux(req.paddr(3), req.mask(15, 8), req.mask(7, 0)) 167 io.uncache.req.bits.id := entryIndex.U 168 io.uncache.req.bits.instrtype := DontCare 169 io.uncache.req.bits.replayCarry := DontCare 170 io.uncache.req.bits.atomic := req.atomic 171 io.uncache.req.bits.nc := req.nc 172 io.uncache.req.bits.memBackTypeMM := req.memBackTypeMM 173 174 io.uncache.resp.ready := true.B 175 176 /* uncahce resp */ 177 when (io.uncache.resp.fire) { 178 uncacheData := io.uncache.resp.bits.data 179 nderr := io.uncache.resp.bits.nderr 180 } 181 182 /* uncahce writeback */ 183 val selUop = req.uop 184 val func = selUop.fuOpType 185 val raddr = req.paddr 186 val rdataSel = LookupTree(raddr(2, 0), List( 187 "b000".U -> uncacheData(63, 0), 188 "b001".U -> uncacheData(63, 8), 189 "b010".U -> uncacheData(63, 16), 190 "b011".U -> uncacheData(63, 24), 191 "b100".U -> uncacheData(63, 32), 192 "b101".U -> uncacheData(63, 40), 193 "b110".U -> uncacheData(63, 48), 194 "b111".U -> uncacheData(63, 56) 195 )) 196 val rdataPartialLoad = rdataHelper(selUop, rdataSel) 197 198 io.mmioOut.valid := false.B 199 io.mmioOut.bits := DontCare 200 io.mmioRawData := DontCare 201 io.ncOut.valid := false.B 202 io.ncOut.bits := DontCare 203 204 when(req.nc){ 205 io.ncOut.valid := (uncacheState === s_wait) 206 io.ncOut.bits := DontCare 207 io.ncOut.bits.uop := selUop 208 io.ncOut.bits.uop.lqIdx := req.uop.lqIdx 209 io.ncOut.bits.uop.exceptionVec(loadAccessFault) := nderr 210 io.ncOut.bits.data := rdataPartialLoad 211 io.ncOut.bits.paddr := req.paddr 212 io.ncOut.bits.vaddr := req.vaddr 213 io.ncOut.bits.nc := true.B 214 io.ncOut.bits.mask := Mux(req.paddr(3), req.mask(15, 8), req.mask(7, 0)) 215 io.ncOut.bits.schedIndex := req.schedIndex 216 io.ncOut.bits.isvec := req.isvec 217 io.ncOut.bits.is128bit := req.is128bit 218 io.ncOut.bits.vecActive := req.vecActive 219 }.otherwise{ 220 io.mmioOut.valid := (uncacheState === s_wait) 221 io.mmioOut.bits := DontCare 222 io.mmioOut.bits.uop := selUop 223 io.mmioOut.bits.uop.lqIdx := req.uop.lqIdx 224 io.mmioOut.bits.uop.exceptionVec(loadAccessFault) := nderr 225 io.mmioOut.bits.data := rdataPartialLoad 226 io.mmioOut.bits.debug.isMMIO := true.B 227 io.mmioOut.bits.debug.isNC := false.B 228 io.mmioOut.bits.debug.paddr := req.paddr 229 io.mmioOut.bits.debug.vaddr := req.vaddr 230 io.mmioRawData.lqData := uncacheData 231 io.mmioRawData.uop := req.uop 232 io.mmioRawData.addrOffset := req.paddr 233 } 234 235 io.exception.valid := writeback 236 io.exception.bits := req 237 io.exception.bits.uop.exceptionVec(loadAccessFault) := nderr 238 239 /* debug log */ 240 XSDebug(io.uncache.req.fire, 241 "uncache req: pc %x addr %x data %x op %x mask %x\n", 242 req.uop.pc, 243 io.uncache.req.bits.addr, 244 io.uncache.req.bits.data, 245 io.uncache.req.bits.cmd, 246 io.uncache.req.bits.mask 247 ) 248 XSInfo(io.ncOut.fire, 249 "int load miss write to cbd robidx %d lqidx %d pc 0x%x mmio %x\n", 250 io.ncOut.bits.uop.robIdx.asUInt, 251 io.ncOut.bits.uop.lqIdx.asUInt, 252 io.ncOut.bits.uop.pc, 253 true.B 254 ) 255 XSInfo(io.mmioOut.fire, 256 "int load miss write to cbd robidx %d lqidx %d pc 0x%x mmio %x\n", 257 io.mmioOut.bits.uop.robIdx.asUInt, 258 io.mmioOut.bits.uop.lqIdx.asUInt, 259 io.mmioOut.bits.uop.pc, 260 true.B 261 ) 262 263} 264 265class LoadQueueUncache(implicit p: Parameters) extends XSModule 266 with HasCircularQueuePtrHelper 267 with HasMemBlockParameters 268{ 269 val io = IO(new Bundle() { 270 /* control */ 271 val redirect = Flipped(Valid(new Redirect)) 272 // mmio commit 273 val rob = Flipped(new RobLsqIO) 274 275 /* transaction */ 276 // enqueue: from ldu s3 277 val req = Vec(LoadPipelineWidth, Flipped(Decoupled(new LqWriteBundle))) 278 // writeback: mmio to ldu s0, s3 279 val mmioOut = Vec(LoadPipelineWidth, DecoupledIO(new MemExuOutput)) 280 val mmioRawData = Vec(LoadPipelineWidth, Output(new LoadDataFromLQBundle)) 281 // writeback: nc to ldu s0--s3 282 val ncOut = Vec(LoadPipelineWidth, Decoupled(new LsPipelineBundle)) 283 // <=>uncache 284 val uncache = new UncacheWordIO 285 286 /* except */ 287 // rollback from frontend when buffer is full 288 val rollback = Output(Valid(new Redirect)) 289 // exception generated by outer bus 290 val exception = Valid(new LqWriteBundle) 291 }) 292 293 /****************************************************************** 294 * Structure 295 ******************************************************************/ 296 val entries = Seq.tabulate(LoadUncacheBufferSize)(i => Module(new UncacheEntry(i))) 297 298 val freeList = Module(new FreeList( 299 size = LoadUncacheBufferSize, 300 allocWidth = LoadPipelineWidth, 301 freeWidth = 4, 302 enablePreAlloc = true, 303 moduleName = "LoadQueueUncache freelist" 304 )) 305 freeList.io := DontCare 306 307 // set default IO 308 entries.foreach { 309 case (e) => 310 e.io.req.valid := false.B 311 e.io.req.bits := DontCare 312 e.io.uncache.req.ready := false.B 313 e.io.uncache.idResp.valid := false.B 314 e.io.uncache.idResp.bits := DontCare 315 e.io.uncache.resp.valid := false.B 316 e.io.uncache.resp.bits := DontCare 317 e.io.ncOut.ready := false.B 318 e.io.mmioOut.ready := false.B 319 } 320 io.uncache.req.valid := false.B 321 io.uncache.req.bits := DontCare 322 io.uncache.resp.ready := false.B 323 for (w <- 0 until LoadPipelineWidth) { 324 io.mmioOut(w).valid := false.B 325 io.mmioOut(w).bits := DontCare 326 io.mmioRawData(w) := DontCare 327 io.ncOut(w).valid := false.B 328 io.ncOut(w).bits := DontCare 329 } 330 331 332 /****************************************************************** 333 * Enqueue 334 * 335 * s1: hold 336 * s2: confirm enqueue and write entry 337 * valid: no redirect, no exception, no replay, is mmio/nc 338 * ready: freelist can allocate 339 ******************************************************************/ 340 341 val s1_sortedVec = HwSort(VecInit(io.req.map { case x => DataWithPtr(x.valid, x.bits, x.bits.uop.robIdx) })) 342 val s1_req = VecInit(s1_sortedVec.map(_.bits)) 343 val s1_valid = VecInit(s1_sortedVec.map(_.valid)) 344 val s2_enqueue = Wire(Vec(LoadPipelineWidth, Bool())) 345 io.req.zipWithIndex.foreach{ case (r, i) => 346 r.ready := true.B 347 } 348 349 // s2: enqueue 350 val s2_req = (0 until LoadPipelineWidth).map(i => {RegEnable(s1_req(i), s1_valid(i))}) 351 val s2_valid = (0 until LoadPipelineWidth).map(i => { 352 RegNext(s1_valid(i)) && 353 !s2_req(i).uop.robIdx.needFlush(RegNext(io.redirect)) && 354 !s2_req(i).uop.robIdx.needFlush(io.redirect) 355 }) 356 val s2_has_exception = s2_req.map(x => ExceptionNO.selectByFu(x.uop.exceptionVec, LduCfg).asUInt.orR) 357 val s2_need_replay = s2_req.map(_.rep_info.need_rep) 358 359 for (w <- 0 until LoadPipelineWidth) { 360 s2_enqueue(w) := s2_valid(w) && !s2_has_exception(w) && !s2_need_replay(w) && (s2_req(w).mmio || s2_req(w).nc) 361 } 362 363 val s2_enqValidVec = Wire(Vec(LoadPipelineWidth, Bool())) 364 val s2_enqIndexVec = Wire(Vec(LoadPipelineWidth, UInt())) 365 366 for (w <- 0 until LoadPipelineWidth) { 367 freeList.io.allocateReq(w) := true.B 368 } 369 370 // freeList real-allocate 371 for (w <- 0 until LoadPipelineWidth) { 372 freeList.io.doAllocate(w) := s2_enqValidVec(w) 373 } 374 375 for (w <- 0 until LoadPipelineWidth) { 376 val offset = PopCount(s2_enqueue.take(w)) 377 s2_enqValidVec(w) := s2_enqueue(w) && freeList.io.canAllocate(offset) 378 s2_enqIndexVec(w) := freeList.io.allocateSlot(offset) 379 } 380 381 382 /****************************************************************** 383 * Uncache Transaction 384 * 385 * 1. uncache req 386 * 2. uncache resp 387 * 3. writeback 388 ******************************************************************/ 389 private val NC_WB_MOD = NCWBPorts.length 390 391 val uncacheReq = Wire(DecoupledIO(io.uncache.req.bits.cloneType)) 392 val mmioSelect = entries.map(e => e.io.mmioSelect).reduce(_ || _) 393 val mmioReq = Wire(DecoupledIO(io.uncache.req.bits.cloneType)) 394 // TODO lyq: It's best to choose in robIdx order / the order in which they enter 395 val ncReqArb = Module(new RRArbiterInit(io.uncache.req.bits.cloneType, LoadUncacheBufferSize)) 396 397 val mmioOut = Wire(DecoupledIO(io.mmioOut(0).bits.cloneType)) 398 val mmioRawData = Wire(io.mmioRawData(0).cloneType) 399 val ncOut = Wire(chiselTypeOf(io.ncOut)) 400 val ncOutValidVec = VecInit(entries.map(e => e.io.ncOut.valid)) 401 val ncOutValidVecRem = SubVec.getMaskRem(ncOutValidVec, NC_WB_MOD) 402 403 // init 404 uncacheReq.valid := false.B 405 uncacheReq.bits := DontCare 406 mmioReq.valid := false.B 407 mmioReq.bits := DontCare 408 mmioOut.valid := false.B 409 mmioOut.bits := DontCare 410 mmioRawData := DontCare 411 for (i <- 0 until LoadUncacheBufferSize) { 412 ncReqArb.io.in(i).valid := false.B 413 ncReqArb.io.in(i).bits := DontCare 414 } 415 for (i <- 0 until LoadPipelineWidth) { 416 ncOut(i).valid := false.B 417 ncOut(i).bits := DontCare 418 } 419 420 entries.zipWithIndex.foreach { 421 case (e, i) => 422 // enqueue 423 for (w <- 0 until LoadPipelineWidth) { 424 when (s2_enqValidVec(w) && (i.U === s2_enqIndexVec(w))) { 425 e.io.req.valid := true.B 426 e.io.req.bits := s2_req(w) 427 } 428 } 429 430 // control 431 e.io.redirect <> io.redirect 432 e.io.rob <> io.rob 433 434 // uncache req, writeback 435 when (e.io.mmioSelect) { 436 mmioReq.valid := e.io.uncache.req.valid 437 mmioReq.bits := e.io.uncache.req.bits 438 e.io.uncache.req.ready := mmioReq.ready 439 440 e.io.mmioOut.ready := mmioOut.ready 441 mmioOut.valid := e.io.mmioOut.valid 442 mmioOut.bits := e.io.mmioOut.bits 443 mmioRawData := e.io.mmioRawData 444 445 }.otherwise{ 446 ncReqArb.io.in(i).valid := e.io.uncache.req.valid 447 ncReqArb.io.in(i).bits := e.io.uncache.req.bits 448 e.io.uncache.req.ready := ncReqArb.io.in(i).ready 449 450 (0 until NC_WB_MOD).map { w => 451 val (idx, ncOutValid) = PriorityEncoderWithFlag(ncOutValidVecRem(w)) 452 val port = NCWBPorts(w) 453 when((i.U === idx) && ncOutValid) { 454 ncOut(port).valid := ncOutValid 455 ncOut(port).bits := e.io.ncOut.bits 456 e.io.ncOut.ready := ncOut(port).ready 457 } 458 } 459 460 } 461 462 // uncache idResp 463 when(i.U === io.uncache.idResp.bits.mid) { 464 e.io.uncache.idResp <> io.uncache.idResp 465 } 466 467 // uncache resp 468 when (e.io.slaveId.valid && e.io.slaveId.bits === io.uncache.resp.bits.id) { 469 e.io.uncache.resp <> io.uncache.resp 470 } 471 472 } 473 474 mmioReq.ready := false.B 475 ncReqArb.io.out.ready := false.B 476 when(mmioSelect){ 477 uncacheReq <> mmioReq 478 }.otherwise{ 479 uncacheReq <> ncReqArb.io.out 480 } 481 482 // uncache Request 483 AddPipelineReg(uncacheReq, io.uncache.req, false.B) 484 485 // uncache Writeback 486 AddPipelineReg(mmioOut, io.mmioOut(UncacheWBPort), false.B) 487 io.mmioRawData(UncacheWBPort) := RegEnable(mmioRawData, mmioOut.fire) 488 489 (0 until LoadPipelineWidth).foreach { i => AddPipelineReg(ncOut(i), io.ncOut(i), false.B) } 490 491 // uncache exception 492 io.exception.valid := Cat(entries.map(_.io.exception.valid)).orR 493 io.exception.bits := ParallelPriorityMux(entries.map(e => 494 (e.io.exception.valid, e.io.exception.bits) 495 )) 496 497 // rob 498 for (i <- 0 until LoadPipelineWidth) { 499 io.rob.mmio(i) := RegNext(s1_valid(i) && s1_req(i).mmio) 500 io.rob.uop(i) := RegEnable(s1_req(i).uop, s1_valid(i)) 501 } 502 503 504 /****************************************************************** 505 * Deallocate 506 ******************************************************************/ 507 // UncacheBuffer deallocate 508 val freeMaskVec = Wire(Vec(LoadUncacheBufferSize, Bool())) 509 510 // init 511 freeMaskVec.map(e => e := false.B) 512 513 // dealloc logic 514 entries.zipWithIndex.foreach { 515 case (e, i) => 516 when ((e.io.mmioSelect && e.io.mmioOut.fire) || e.io.ncOut.fire || e.io.flush) { 517 freeMaskVec(i) := true.B 518 } 519 } 520 521 freeList.io.free := freeMaskVec.asUInt 522 523 524 /****************************************************************** 525 * Uncache rollback detection 526 * 527 * When uncache loads enqueue, it searches uncache loads, They can not enqueue and need re-execution. 528 * 529 * Cycle 0: uncache enqueue. 530 * Cycle 1: Select oldest uncache loads. 531 * Cycle 2: Redirect Fire. 532 * Choose the oldest load from LoadPipelineWidth oldest loads. 533 * Prepare redirect request according to the detected rejection. 534 * Fire redirect request (if valid) 535 * 536 * Load_S3 .... Load_S3 537 * stage 0: lq lq 538 * | | (can not enqueue) 539 * stage 1: lq lq 540 * | | 541 * --------------- 542 * | 543 * stage 2: lq 544 * | 545 * rollback req 546 * 547 ******************************************************************/ 548 def selectOldestRedirect(xs: Seq[Valid[Redirect]]): Vec[Bool] = { 549 val compareVec = (0 until xs.length).map(i => (0 until i).map(j => isAfter(xs(j).bits.robIdx, xs(i).bits.robIdx))) 550 val resultOnehot = VecInit((0 until xs.length).map(i => Cat((0 until xs.length).map(j => 551 (if (j < i) !xs(j).valid || compareVec(i)(j) 552 else if (j == i) xs(i).valid 553 else !xs(j).valid || !compareVec(j)(i)) 554 )).andR)) 555 resultOnehot 556 } 557 val reqNeedCheck = VecInit((0 until LoadPipelineWidth).map(w => 558 s2_enqueue(w) && !s2_enqValidVec(w) 559 )) 560 val reqSelUops = VecInit(s2_req.map(_.uop)) 561 val allRedirect = (0 until LoadPipelineWidth).map(i => { 562 val redirect = Wire(Valid(new Redirect)) 563 redirect.valid := reqNeedCheck(i) 564 redirect.bits := DontCare 565 redirect.bits.isRVC := reqSelUops(i).preDecodeInfo.isRVC 566 redirect.bits.robIdx := reqSelUops(i).robIdx 567 redirect.bits.ftqIdx := reqSelUops(i).ftqPtr 568 redirect.bits.ftqOffset := reqSelUops(i).ftqOffset 569 redirect.bits.level := RedirectLevel.flush 570 redirect.bits.cfiUpdate.target := reqSelUops(i).pc // TODO: check if need pc 571 redirect.bits.debug_runahead_checkpoint_id := reqSelUops(i).debugInfo.runahead_checkpoint_id 572 redirect 573 }) 574 val oldestOneHot = selectOldestRedirect(allRedirect) 575 val oldestRedirect = Mux1H(oldestOneHot, allRedirect) 576 val lastCycleRedirect = Wire(Valid(new Redirect)) 577 lastCycleRedirect.valid := RegNext(io.redirect.valid) 578 lastCycleRedirect.bits := RegEnable(io.redirect.bits, io.redirect.valid) 579 val lastLastCycleRedirect = Wire(Valid(new Redirect)) 580 lastLastCycleRedirect.valid := RegNext(lastCycleRedirect.valid) 581 lastLastCycleRedirect.bits := RegEnable(lastCycleRedirect.bits, lastCycleRedirect.valid) 582 io.rollback.valid := GatedValidRegNext(oldestRedirect.valid && 583 !oldestRedirect.bits.robIdx.needFlush(io.redirect) && 584 !oldestRedirect.bits.robIdx.needFlush(lastCycleRedirect) && 585 !oldestRedirect.bits.robIdx.needFlush(lastLastCycleRedirect)) 586 io.rollback.bits := RegEnable(oldestRedirect.bits, oldestRedirect.valid) 587 588 589 /****************************************************************** 590 * Perf Counter 591 ******************************************************************/ 592 val validCount = freeList.io.validCount 593 val allowEnqueue = !freeList.io.empty 594 QueuePerf(LoadUncacheBufferSize, validCount, !allowEnqueue) 595 596 XSPerfAccumulate("mmio_uncache_req", io.uncache.req.fire && !io.uncache.req.bits.nc) 597 XSPerfAccumulate("mmio_writeback_success", io.mmioOut(0).fire) 598 XSPerfAccumulate("mmio_writeback_blocked", io.mmioOut(0).valid && !io.mmioOut(0).ready) 599 XSPerfAccumulate("nc_uncache_req", io.uncache.req.fire && io.uncache.req.bits.nc) 600 XSPerfAccumulate("nc_writeback_success", io.ncOut(0).fire) 601 XSPerfAccumulate("nc_writeback_blocked", io.ncOut(0).valid && !io.ncOut(0).ready) 602 XSPerfAccumulate("uncache_full_rollback", io.rollback.valid) 603 604 val perfEvents: Seq[(String, UInt)] = Seq( 605 ("mmio_uncache_req", io.uncache.req.fire && !io.uncache.req.bits.nc), 606 ("mmio_writeback_success", io.mmioOut(0).fire), 607 ("mmio_writeback_blocked", io.mmioOut(0).valid && !io.mmioOut(0).ready), 608 ("nc_uncache_req", io.uncache.req.fire && io.uncache.req.bits.nc), 609 ("nc_writeback_success", io.ncOut(0).fire), 610 ("nc_writeback_blocked", io.ncOut(0).valid && !io.ncOut(0).ready), 611 ("uncache_full_rollback", io.rollback.valid) 612 ) 613 // end 614} 615