1e4f69d78Ssfencevma/*************************************************************************************** 2e4f69d78Ssfencevma* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3e4f69d78Ssfencevma* Copyright (c) 2020-2021 Peng Cheng Laboratory 4e4f69d78Ssfencevma* 5e4f69d78Ssfencevma* XiangShan is licensed under Mulan PSL v2. 6e4f69d78Ssfencevma* You can use this software according to the terms and conditions of the Mulan PSL v2. 7e4f69d78Ssfencevma* You may obtain a copy of Mulan PSL v2 at: 8e4f69d78Ssfencevma* http://license.coscl.org.cn/MulanPSL2 9e4f69d78Ssfencevma* 10e4f69d78Ssfencevma* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11e4f69d78Ssfencevma* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12e4f69d78Ssfencevma* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13e4f69d78Ssfencevma* 14e4f69d78Ssfencevma* See the Mulan PSL v2 for more details. 15e4f69d78Ssfencevma***************************************************************************************/ 16e4f69d78Ssfencevma 17e4f69d78Ssfencevmapackage xiangshan.mem 18e4f69d78Ssfencevma 19e4f69d78Ssfencevmaimport chisel3._ 20e4f69d78Ssfencevmaimport chisel3.util._ 218891a219SYinan Xuimport org.chipsalliance.cde.config._ 22e4f69d78Ssfencevmaimport xiangshan._ 23e4f69d78Ssfencevmaimport xiangshan.backend.rob.RobPtr 24e4f69d78Ssfencevmaimport xiangshan.cache._ 25e4f69d78Ssfencevmaimport xiangshan.frontend.FtqPtr 26e4f69d78Ssfencevmaimport xiangshan.mem.mdp._ 27e4f69d78Ssfencevmaimport utils._ 28e4f69d78Ssfencevmaimport utility._ 29dfb4c5dcSXuan Huimport xiangshan.backend.Bundles.DynInst 30e4f69d78Ssfencevma 31e4f69d78Ssfencevmaclass LoadQueueRAW(implicit p: Parameters) extends XSModule 32e4f69d78Ssfencevma with HasDCacheParameters 33e4f69d78Ssfencevma with HasCircularQueuePtrHelper 34e4f69d78Ssfencevma with HasLoadHelper 35e4f69d78Ssfencevma with HasPerfEvents 36e4f69d78Ssfencevma{ 37e4f69d78Ssfencevma val io = IO(new Bundle() { 3814a67055Ssfencevma // control 39e4f69d78Ssfencevma val redirect = Flipped(ValidIO(new Redirect)) 40627be78bSgood-circle val vecFeedback = Vec(VecLoadPipelineWidth, Flipped(ValidIO(new FeedbackToLsqIO))) 4114a67055Ssfencevma 4214a67055Ssfencevma // violation query 4314a67055Ssfencevma val query = Vec(LoadPipelineWidth, Flipped(new LoadNukeQueryIO)) 4414a67055Ssfencevma 4514a67055Ssfencevma // from store unit s1 46e4f69d78Ssfencevma val storeIn = Vec(StorePipelineWidth, Flipped(Valid(new LsPipelineBundle))) 4714a67055Ssfencevma 4814a67055Ssfencevma // global rollback flush 4916ede6bbSweiding liu val rollback = Vec(StorePipelineWidth,Output(Valid(new Redirect))) 5014a67055Ssfencevma 5114a67055Ssfencevma // to LoadQueueReplay 52e4f69d78Ssfencevma val stAddrReadySqPtr = Input(new SqPtr) 53e4f69d78Ssfencevma val stIssuePtr = Input(new SqPtr) 54e4f69d78Ssfencevma val lqFull = Output(Bool()) 55e4f69d78Ssfencevma }) 56e4f69d78Ssfencevma 57*549073a0Scz4e private def PartialPAddrWidth: Int = 24 58*549073a0Scz4e private def genPartialPAddr(paddr: UInt) = { 59*549073a0Scz4e paddr(DCacheVWordOffset + PartialPAddrWidth - 1, DCacheVWordOffset) 60*549073a0Scz4e } 61*549073a0Scz4e 62e4f69d78Ssfencevma println("LoadQueueRAW: size " + LoadQueueRAWSize) 63e4f69d78Ssfencevma // LoadQueueRAW field 64e4f69d78Ssfencevma // +-------+--------+-------+-------+-----------+ 65e4f69d78Ssfencevma // | Valid | uop |PAddr | Mask | Datavalid | 66e4f69d78Ssfencevma // +-------+--------+-------+-------+-----------+ 67e4f69d78Ssfencevma // 68e4f69d78Ssfencevma // Field descriptions: 69e4f69d78Ssfencevma // Allocated : entry has been allocated already 70e4f69d78Ssfencevma // MicroOp : inst's microOp 71e4f69d78Ssfencevma // PAddr : physical address. 72e4f69d78Ssfencevma // Mask : data mask 73e4f69d78Ssfencevma // Datavalid : data valid 74e4f69d78Ssfencevma // 75e4f69d78Ssfencevma val allocated = RegInit(VecInit(List.fill(LoadQueueRAWSize)(false.B))) // The control signals need to explicitly indicate the initial value 76dfb4c5dcSXuan Hu val uop = Reg(Vec(LoadQueueRAWSize, new DynInst)) 77e4f69d78Ssfencevma val paddrModule = Module(new LqPAddrModule( 78*549073a0Scz4e gen = UInt(PartialPAddrWidth.W), 79e4f69d78Ssfencevma numEntries = LoadQueueRAWSize, 80e4f69d78Ssfencevma numRead = LoadPipelineWidth, 81e4f69d78Ssfencevma numWrite = LoadPipelineWidth, 82e4f69d78Ssfencevma numWBank = LoadQueueNWriteBanks, 83e4f69d78Ssfencevma numWDelay = 2, 84e4f69d78Ssfencevma numCamPort = StorePipelineWidth 85e4f69d78Ssfencevma )) 86e4f69d78Ssfencevma paddrModule.io := DontCare 87e4f69d78Ssfencevma val maskModule = Module(new LqMaskModule( 88cdbff57cSHaoyuan Feng gen = UInt((VLEN/8).W), 89e4f69d78Ssfencevma numEntries = LoadQueueRAWSize, 90e4f69d78Ssfencevma numRead = LoadPipelineWidth, 91e4f69d78Ssfencevma numWrite = LoadPipelineWidth, 92e4f69d78Ssfencevma numWBank = LoadQueueNWriteBanks, 93e4f69d78Ssfencevma numWDelay = 2, 94e4f69d78Ssfencevma numCamPort = StorePipelineWidth 95e4f69d78Ssfencevma )) 96e4f69d78Ssfencevma maskModule.io := DontCare 97e4f69d78Ssfencevma val datavalid = RegInit(VecInit(List.fill(LoadQueueRAWSize)(false.B))) 98e4f69d78Ssfencevma 99e4f69d78Ssfencevma // freeliset: store valid entries index. 100e4f69d78Ssfencevma // +---+---+--------------+-----+-----+ 101e4f69d78Ssfencevma // | 0 | 1 | ...... | n-2 | n-1 | 102e4f69d78Ssfencevma // +---+---+--------------+-----+-----+ 103e4f69d78Ssfencevma val freeList = Module(new FreeList( 104e4f69d78Ssfencevma size = LoadQueueRAWSize, 105e4f69d78Ssfencevma allocWidth = LoadPipelineWidth, 106e4f69d78Ssfencevma freeWidth = 4, 107f275998aSsfencevma enablePreAlloc = true, 108e4f69d78Ssfencevma moduleName = "LoadQueueRAW freelist" 109e4f69d78Ssfencevma )) 110e4f69d78Ssfencevma freeList.io := DontCare 111e4f69d78Ssfencevma 112e4f69d78Ssfencevma // LoadQueueRAW enqueue 113e4f69d78Ssfencevma val canEnqueue = io.query.map(_.req.valid) 114e4f69d78Ssfencevma val cancelEnqueue = io.query.map(_.req.bits.uop.robIdx.needFlush(io.redirect)) 115e4f69d78Ssfencevma val allAddrCheck = io.stIssuePtr === io.stAddrReadySqPtr 116e4f69d78Ssfencevma val hasAddrInvalidStore = io.query.map(_.req.bits.uop.sqIdx).map(sqIdx => { 117e4f69d78Ssfencevma Mux(!allAddrCheck, isBefore(io.stAddrReadySqPtr, sqIdx), false.B) 118e4f69d78Ssfencevma }) 119e4f69d78Ssfencevma val needEnqueue = canEnqueue.zip(hasAddrInvalidStore).zip(cancelEnqueue).map { case ((v, r), c) => v && r && !c } 120e4f69d78Ssfencevma 121e4f69d78Ssfencevma // Allocate logic 122f275998aSsfencevma val acceptedVec = Wire(Vec(LoadPipelineWidth, Bool())) 12331fae68eSYanqin Li val enqIndexVec = Wire(Vec(LoadPipelineWidth, UInt(log2Up(LoadQueueRAWSize).W))) 124e4f69d78Ssfencevma 125e4f69d78Ssfencevma // Enqueue 126e4f69d78Ssfencevma for ((enq, w) <- io.query.map(_.req).zipWithIndex) { 127f275998aSsfencevma acceptedVec(w) := false.B 128e4f69d78Ssfencevma paddrModule.io.wen(w) := false.B 129e4f69d78Ssfencevma maskModule.io.wen(w) := false.B 130e4f69d78Ssfencevma freeList.io.doAllocate(w) := false.B 131e4f69d78Ssfencevma 132f275998aSsfencevma freeList.io.allocateReq(w) := true.B 133e4f69d78Ssfencevma 134e4f69d78Ssfencevma // Allocate ready 135f275998aSsfencevma val offset = PopCount(needEnqueue.take(w)) 136f275998aSsfencevma val canAccept = freeList.io.canAllocate(offset) 137f275998aSsfencevma val enqIndex = freeList.io.allocateSlot(offset) 138f275998aSsfencevma enq.ready := Mux(needEnqueue(w), canAccept, true.B) 139e4f69d78Ssfencevma 140f275998aSsfencevma enqIndexVec(w) := enqIndex 141e4f69d78Ssfencevma when (needEnqueue(w) && enq.ready) { 142f275998aSsfencevma acceptedVec(w) := true.B 143f275998aSsfencevma 144e4f69d78Ssfencevma val debug_robIdx = enq.bits.uop.robIdx.asUInt 145e4f69d78Ssfencevma XSError(allocated(enqIndex), p"LoadQueueRAW: You can not write an valid entry! check: ldu $w, robIdx $debug_robIdx") 146e4f69d78Ssfencevma 147e4f69d78Ssfencevma freeList.io.doAllocate(w) := true.B 148e4f69d78Ssfencevma 149e4f69d78Ssfencevma // Allocate new entry 150e4f69d78Ssfencevma allocated(enqIndex) := true.B 151e4f69d78Ssfencevma 152e4f69d78Ssfencevma // Write paddr 153e4f69d78Ssfencevma paddrModule.io.wen(w) := true.B 154e4f69d78Ssfencevma paddrModule.io.waddr(w) := enqIndex 155*549073a0Scz4e paddrModule.io.wdata(w) := genPartialPAddr(enq.bits.paddr) 156e4f69d78Ssfencevma 157e4f69d78Ssfencevma // Write mask 158e4f69d78Ssfencevma maskModule.io.wen(w) := true.B 159e4f69d78Ssfencevma maskModule.io.waddr(w) := enqIndex 160e4f69d78Ssfencevma maskModule.io.wdata(w) := enq.bits.mask 161e4f69d78Ssfencevma 162e4f69d78Ssfencevma // Fill info 163e4f69d78Ssfencevma uop(enqIndex) := enq.bits.uop 16414a67055Ssfencevma datavalid(enqIndex) := enq.bits.data_valid 165e4f69d78Ssfencevma } 166e4f69d78Ssfencevma } 167e4f69d78Ssfencevma 168e4f69d78Ssfencevma for ((query, w) <- io.query.map(_.resp).zipWithIndex) { 169e4f69d78Ssfencevma query.valid := RegNext(io.query(w).req.valid) 17014a67055Ssfencevma query.bits.rep_frm_fetch := RegNext(false.B) 171e4f69d78Ssfencevma } 172e4f69d78Ssfencevma 173e4f69d78Ssfencevma // LoadQueueRAW deallocate 174e4f69d78Ssfencevma val freeMaskVec = Wire(Vec(LoadQueueRAWSize, Bool())) 175e4f69d78Ssfencevma 176e4f69d78Ssfencevma // init 177e4f69d78Ssfencevma freeMaskVec.map(e => e := false.B) 178e4f69d78Ssfencevma 179e4f69d78Ssfencevma // when the stores that "older than" current load address were ready. 180e4f69d78Ssfencevma // current load will be released. 181627be78bSgood-circle val vecLdCanceltmp = Wire(Vec(LoadQueueRAWSize, Vec(VecLoadPipelineWidth, Bool()))) 18226af847eSgood-circle val vecLdCancel = Wire(Vec(LoadQueueRAWSize, Bool())) 183e4f69d78Ssfencevma for (i <- 0 until LoadQueueRAWSize) { 184e4f69d78Ssfencevma val deqNotBlock = Mux(!allAddrCheck, !isBefore(io.stAddrReadySqPtr, uop(i).sqIdx), true.B) 185e4f69d78Ssfencevma val needCancel = uop(i).robIdx.needFlush(io.redirect) 186627be78bSgood-circle val fbk = io.vecFeedback 187627be78bSgood-circle for (j <- 0 until VecLoadPipelineWidth) { 188ff9b84b9Slwd vecLdCanceltmp(i)(j) := allocated(i) && fbk(j).valid && fbk(j).bits.isFlush && uop(i).robIdx === fbk(j).bits.robidx && uop(i).uopIdx === fbk(j).bits.uopidx 189627be78bSgood-circle } 190627be78bSgood-circle vecLdCancel(i) := vecLdCanceltmp(i).reduce(_ || _) 191e4f69d78Ssfencevma 19226af847eSgood-circle when (allocated(i) && (deqNotBlock || needCancel || vecLdCancel(i))) { 193e4f69d78Ssfencevma allocated(i) := false.B 194e4f69d78Ssfencevma freeMaskVec(i) := true.B 195e4f69d78Ssfencevma } 196e4f69d78Ssfencevma } 197e4f69d78Ssfencevma 198e4f69d78Ssfencevma // if need replay deallocate entry 1995003e6f8SHuijin Li val lastCanAccept = GatedValidRegNext(acceptedVec) 2005003e6f8SHuijin Li val lastAllocIndex = GatedRegNext(enqIndexVec) 201e4f69d78Ssfencevma 20214a67055Ssfencevma for ((revoke, w) <- io.query.map(_.revoke).zipWithIndex) { 20314a67055Ssfencevma val revokeValid = revoke && lastCanAccept(w) 20414a67055Ssfencevma val revokeIndex = lastAllocIndex(w) 205e4f69d78Ssfencevma 20614a67055Ssfencevma when (allocated(revokeIndex) && revokeValid) { 20714a67055Ssfencevma allocated(revokeIndex) := false.B 20814a67055Ssfencevma freeMaskVec(revokeIndex) := true.B 209e4f69d78Ssfencevma } 210e4f69d78Ssfencevma } 211e4f69d78Ssfencevma freeList.io.free := freeMaskVec.asUInt 212e4f69d78Ssfencevma 213e4f69d78Ssfencevma io.lqFull := freeList.io.empty 214e4f69d78Ssfencevma 215e4f69d78Ssfencevma /** 216e4f69d78Ssfencevma * Store-Load Memory violation detection 217e4f69d78Ssfencevma * Scheme 1(Current scheme): flush the pipeline then re-fetch from the load instruction (like old load queue). 218e4f69d78Ssfencevma * Scheme 2 : re-fetch instructions from the first instruction after the store instruction. 219e4f69d78Ssfencevma * 220e4f69d78Ssfencevma * When store writes back, it searches LoadQueue for younger load instructions 221e4f69d78Ssfencevma * with the same load physical address. They loaded wrong data and need re-execution. 222e4f69d78Ssfencevma * 223e4f69d78Ssfencevma * Cycle 0: Store Writeback 224e4f69d78Ssfencevma * Generate match vector for store address with rangeMask(stPtr, enqPtr). 225e4f69d78Ssfencevma * Cycle 1: Select oldest load from select group. 226e4f69d78Ssfencevma * Cycle x: Redirect Fire 227e4f69d78Ssfencevma * Choose the oldest load from LoadPipelineWidth oldest loads. 228e4f69d78Ssfencevma * Prepare redirect request according to the detected violation. 229e4f69d78Ssfencevma * Fire redirect request (if valid) 230e4f69d78Ssfencevma */ 231e4f69d78Ssfencevma // SelectGroup 0 SelectGroup 1 SelectGroup y 232e4f69d78Ssfencevma // stage 0: lq lq lq ...... lq lq lq ....... lq lq lq 233e4f69d78Ssfencevma // | | | | | | | | | 234e4f69d78Ssfencevma // stage 1: lq lq lq ...... lq lq lq ....... lq lq lq 235e4f69d78Ssfencevma // \ | / ...... \ | / ....... \ | / 236e4f69d78Ssfencevma // stage 2: lq lq lq 237e4f69d78Ssfencevma // \ | / ....... \ | / ........ \ | / 238e4f69d78Ssfencevma // stage 3: lq lq lq 239e4f69d78Ssfencevma // ... 240e4f69d78Ssfencevma // ... 241e4f69d78Ssfencevma // | 242e4f69d78Ssfencevma // stage x: lq 243e4f69d78Ssfencevma // | 244e4f69d78Ssfencevma // rollback req 245e4f69d78Ssfencevma 246e4f69d78Ssfencevma // select logic 247e4f69d78Ssfencevma val SelectGroupSize = RollbackGroupSize 248e4f69d78Ssfencevma val lgSelectGroupSize = log2Ceil(SelectGroupSize) 249e4f69d78Ssfencevma val TotalSelectCycles = scala.math.ceil(log2Ceil(LoadQueueRAWSize).toFloat / lgSelectGroupSize).toInt + 1 250e4f69d78Ssfencevma 251e4f69d78Ssfencevma def selectPartialOldest[T <: XSBundleWithMicroOp](valid: Seq[Bool], bits: Seq[T]): (Seq[Bool], Seq[T]) = { 252e4f69d78Ssfencevma assert(valid.length == bits.length) 253e4f69d78Ssfencevma if (valid.length == 0 || valid.length == 1) { 254e4f69d78Ssfencevma (valid, bits) 255e4f69d78Ssfencevma } else if (valid.length == 2) { 256e4f69d78Ssfencevma val res = Seq.fill(2)(Wire(ValidIO(chiselTypeOf(bits(0))))) 257e4f69d78Ssfencevma for (i <- res.indices) { 258e4f69d78Ssfencevma res(i).valid := valid(i) 259e4f69d78Ssfencevma res(i).bits := bits(i) 260e4f69d78Ssfencevma } 261e4f69d78Ssfencevma val oldest = Mux(valid(0) && valid(1), Mux(isAfter(bits(0).uop.robIdx, bits(1).uop.robIdx), res(1), res(0)), Mux(valid(0) && !valid(1), res(0), res(1))) 262e4f69d78Ssfencevma (Seq(oldest.valid), Seq(oldest.bits)) 263e4f69d78Ssfencevma } else { 264e4f69d78Ssfencevma val left = selectPartialOldest(valid.take(valid.length / 2), bits.take(bits.length / 2)) 265e4f69d78Ssfencevma val right = selectPartialOldest(valid.takeRight(valid.length - (valid.length / 2)), bits.takeRight(bits.length - (bits.length / 2))) 266e4f69d78Ssfencevma selectPartialOldest(left._1 ++ right._1, left._2 ++ right._2) 267e4f69d78Ssfencevma } 268e4f69d78Ssfencevma } 269e4f69d78Ssfencevma 270e4f69d78Ssfencevma def selectOldest[T <: XSBundleWithMicroOp](valid: Seq[Bool], bits: Seq[T]): (Seq[Bool], Seq[T]) = { 271e4f69d78Ssfencevma assert(valid.length == bits.length) 272e4f69d78Ssfencevma val numSelectGroups = scala.math.ceil(valid.length.toFloat / SelectGroupSize).toInt 273e4f69d78Ssfencevma 274e4f69d78Ssfencevma // group info 275660213bdSsfencevma val selectValidGroups = valid.grouped(SelectGroupSize).toList 276660213bdSsfencevma val selectBitsGroups = bits.grouped(SelectGroupSize).toList 277e4f69d78Ssfencevma // select logic 278e4f69d78Ssfencevma if (valid.length <= SelectGroupSize) { 279e4f69d78Ssfencevma val (selValid, selBits) = selectPartialOldest(valid, bits) 2805003e6f8SHuijin Li val selValidNext = GatedValidRegNext(selValid(0)) 2815003e6f8SHuijin Li val selBitsNext = RegEnable(selBits(0), selValid(0)) 28216ede6bbSweiding liu (Seq(selValidNext && !selBitsNext.uop.robIdx.needFlush(RegNext(io.redirect))), Seq(selBitsNext)) 283e4f69d78Ssfencevma } else { 284e4f69d78Ssfencevma val select = (0 until numSelectGroups).map(g => { 285e4f69d78Ssfencevma val (selValid, selBits) = selectPartialOldest(selectValidGroups(g), selectBitsGroups(g)) 286f275998aSsfencevma val selValidNext = RegNext(selValid(0)) 2875003e6f8SHuijin Li val selBitsNext = RegEnable(selBits(0), selValid(0)) 288f275998aSsfencevma (selValidNext && !selBitsNext.uop.robIdx.needFlush(io.redirect) && !selBitsNext.uop.robIdx.needFlush(RegNext(io.redirect)), selBitsNext) 289e4f69d78Ssfencevma }) 290e4f69d78Ssfencevma selectOldest(select.map(_._1), select.map(_._2)) 291e4f69d78Ssfencevma } 292e4f69d78Ssfencevma } 293e4f69d78Ssfencevma 29426af847eSgood-circle val storeIn = io.storeIn 295e4f69d78Ssfencevma 29620a5248fSzhanglinjuan def detectRollback(i: Int) = { 297*549073a0Scz4e paddrModule.io.violationMdata(i) := genPartialPAddr(RegEnable(storeIn(i).bits.paddr, storeIn(i).valid)) 2985003e6f8SHuijin Li maskModule.io.violationMdata(i) := RegEnable(storeIn(i).bits.mask, storeIn(i).valid) 29920a5248fSzhanglinjuan 300aebc38d1Ssfencevma val addrMaskMatch = paddrModule.io.violationMmask(i).asUInt & maskModule.io.violationMmask(i).asUInt 3015003e6f8SHuijin Li val entryNeedCheck = GatedValidRegNext(VecInit((0 until LoadQueueRAWSize).map(j => { 302520ec528SXuan Hu allocated(j) && storeIn(i).valid && isAfter(uop(j).robIdx, storeIn(i).bits.uop.robIdx) && datavalid(j) && !uop(j).robIdx.needFlush(io.redirect) 303e4f69d78Ssfencevma }))) 304e4f69d78Ssfencevma val lqViolationSelVec = VecInit((0 until LoadQueueRAWSize).map(j => { 305e4f69d78Ssfencevma addrMaskMatch(j) && entryNeedCheck(j) 306e4f69d78Ssfencevma })) 307e4f69d78Ssfencevma 308e4f69d78Ssfencevma val lqViolationSelUopExts = uop.map(uop => { 309e4f69d78Ssfencevma val wrapper = Wire(new XSBundleWithMicroOp) 310e4f69d78Ssfencevma wrapper.uop := uop 311e4f69d78Ssfencevma wrapper 312e4f69d78Ssfencevma }) 313e4f69d78Ssfencevma 314e4f69d78Ssfencevma // select logic 315520ec528SXuan Hu val lqSelect: (Seq[Bool], Seq[XSBundleWithMicroOp]) = selectOldest(lqViolationSelVec, lqViolationSelUopExts) 316e4f69d78Ssfencevma 317e4f69d78Ssfencevma // select one inst 318e4f69d78Ssfencevma val lqViolation = lqSelect._1(0) 319e4f69d78Ssfencevma val lqViolationUop = lqSelect._2(0).uop 320e4f69d78Ssfencevma 321e4f69d78Ssfencevma XSDebug( 322e4f69d78Ssfencevma lqViolation, 323e4f69d78Ssfencevma "need rollback (ld wb before store) pc %x robidx %d target %x\n", 32420a5248fSzhanglinjuan storeIn(i).bits.uop.pc, storeIn(i).bits.uop.robIdx.asUInt, lqViolationUop.robIdx.asUInt 325e4f69d78Ssfencevma ) 326e4f69d78Ssfencevma 327e4f69d78Ssfencevma (lqViolation, lqViolationUop) 328e4f69d78Ssfencevma } 329e4f69d78Ssfencevma 330e4f69d78Ssfencevma // select rollback (part1) and generate rollback request 331e4f69d78Ssfencevma // rollback check 332e4f69d78Ssfencevma // Lq rollback seq check is done in s3 (next stage), as getting rollbackLq MicroOp is slow 33371489510SXuan Hu val rollbackLqWb = Wire(Vec(StorePipelineWidth, Valid(new DynInst))) 334e4f69d78Ssfencevma val stFtqIdx = Wire(Vec(StorePipelineWidth, new FtqPtr)) 335e4f69d78Ssfencevma val stFtqOffset = Wire(Vec(StorePipelineWidth, UInt(log2Up(PredictWidth).W))) 336e4f69d78Ssfencevma for (w <- 0 until StorePipelineWidth) { 337e4f69d78Ssfencevma val detectedRollback = detectRollback(w) 33820a5248fSzhanglinjuan rollbackLqWb(w).valid := detectedRollback._1 && DelayN(storeIn(w).valid && !storeIn(w).bits.miss, TotalSelectCycles) 339cd2ff98bShappy-lx rollbackLqWb(w).bits := detectedRollback._2 3405003e6f8SHuijin Li stFtqIdx(w) := DelayNWithValid(storeIn(w).bits.uop.ftqPtr, storeIn(w).valid, TotalSelectCycles)._2 3415003e6f8SHuijin Li stFtqOffset(w) := DelayNWithValid(storeIn(w).bits.uop.ftqOffset, storeIn(w).valid, TotalSelectCycles)._2 342e4f69d78Ssfencevma } 343e4f69d78Ssfencevma 344e4f69d78Ssfencevma // select rollback (part2), generate rollback request, then fire rollback request 345e4f69d78Ssfencevma // Note that we use robIdx - 1.U to flush the load instruction itself. 346e4f69d78Ssfencevma // Thus, here if last cycle's robIdx equals to this cycle's robIdx, it still triggers the redirect. 347e4f69d78Ssfencevma 348e4f69d78Ssfencevma // select uop in parallel 34916ede6bbSweiding liu 350cd2ff98bShappy-lx val allRedirect = (0 until StorePipelineWidth).map(i => { 351cd2ff98bShappy-lx val redirect = Wire(Valid(new Redirect)) 352cd2ff98bShappy-lx redirect.valid := rollbackLqWb(i).valid 353cd2ff98bShappy-lx redirect.bits := DontCare 35471489510SXuan Hu redirect.bits.isRVC := rollbackLqWb(i).bits.preDecodeInfo.isRVC 355cd2ff98bShappy-lx redirect.bits.robIdx := rollbackLqWb(i).bits.robIdx 3568241cb85SXuan Hu redirect.bits.ftqIdx := rollbackLqWb(i).bits.ftqPtr 3578241cb85SXuan Hu redirect.bits.ftqOffset := rollbackLqWb(i).bits.ftqOffset 358cd2ff98bShappy-lx redirect.bits.stFtqIdx := stFtqIdx(i) 359cd2ff98bShappy-lx redirect.bits.stFtqOffset := stFtqOffset(i) 360cd2ff98bShappy-lx redirect.bits.level := RedirectLevel.flush 3618241cb85SXuan Hu redirect.bits.cfiUpdate.target := rollbackLqWb(i).bits.pc 362cd2ff98bShappy-lx redirect.bits.debug_runahead_checkpoint_id := rollbackLqWb(i).bits.debugInfo.runahead_checkpoint_id 363cd2ff98bShappy-lx redirect 364cd2ff98bShappy-lx }) 36516ede6bbSweiding liu io.rollback := allRedirect 366e4f69d78Ssfencevma 367e4f69d78Ssfencevma // perf cnt 368e4f69d78Ssfencevma val canEnqCount = PopCount(io.query.map(_.req.fire)) 369e4f69d78Ssfencevma val validCount = freeList.io.validCount 370e4f69d78Ssfencevma val allowEnqueue = validCount <= (LoadQueueRAWSize - LoadPipelineWidth).U 37116ede6bbSweiding liu val rollbaclValid = io.rollback.map(_.valid).reduce(_ || _).asUInt 372e4f69d78Ssfencevma 373e4f69d78Ssfencevma QueuePerf(LoadQueueRAWSize, validCount, !allowEnqueue) 374e4f69d78Ssfencevma XSPerfAccumulate("enqs", canEnqCount) 37516ede6bbSweiding liu XSPerfAccumulate("stld_rollback", rollbaclValid) 376e4f69d78Ssfencevma val perfEvents: Seq[(String, UInt)] = Seq( 377e4f69d78Ssfencevma ("enq ", canEnqCount), 37816ede6bbSweiding liu ("stld_rollback", rollbaclValid), 379e4f69d78Ssfencevma ) 380e4f69d78Ssfencevma generatePerfEvent() 381e4f69d78Ssfencevma // end 382e4f69d78Ssfencevma}