1package xiangshan.backend.issue 2 3import org.chipsalliance.cde.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import utility.HasCircularQueuePtrHelper 7import utils._ 8import utility._ 9import xiangshan._ 10import xiangshan.backend.Bundles._ 11import xiangshan.backend.datapath.DataConfig.VAddrData 12import xiangshan.backend.datapath.DataSource 13import xiangshan.backend.fu.FuType 14import xiangshan.backend.fu.vector.Utils.NOnes 15import xiangshan.backend.rob.RobPtr 16import xiangshan.mem.{LqPtr, MemWaitUpdateReq, SqPtr} 17import xiangshan.backend.issue.EntryBundles._ 18 19class Entries(implicit p: Parameters, params: IssueBlockParams) extends XSModule { 20 override def desiredName: String = params.getEntryName 21 22 require(params.numEnq <= 2, "number of enq should be no more than 2") 23 24 private val EnqEntryNum = params.numEnq 25 private val OthersEntryNum = params.numEntries - params.numEnq 26 private val SimpEntryNum = params.numSimp 27 private val CompEntryNum = params.numComp 28 val io = IO(new EntriesIO) 29 30 // only memAddrIQ use it 31 val memEtyResps: Seq[ValidIO[EntryDeqRespBundle]] = { 32 val resps = 33 if (params.isLdAddrIQ && !params.isStAddrIQ) //LDU 34 Seq(io.fromLoad.get.finalIssueResp, io.fromLoad.get.memAddrIssueResp) 35 else if (params.isLdAddrIQ && params.isStAddrIQ || params.isHyAddrIQ) //HYU 36 Seq(io.fromLoad.get.finalIssueResp, io.fromLoad.get.memAddrIssueResp, io.fromMem.get.fastResp, io.fromMem.get.slowResp) 37 else if (params.isStAddrIQ) //STU 38 Seq(io.fromMem.get.slowResp) 39 else if (params.isVecLduIQ && params.isVecStuIQ) // Vector store IQ need no vecLdIn.resp, but for now vector store share the vector load IQ 40 Seq(io.vecLdIn.get.resp, io.fromMem.get.slowResp) 41 else if (params.isVecLduIQ) 42 Seq(io.vecLdIn.get.resp) 43 else if (params.isVecStuIQ) 44 Seq(io.fromMem.get.slowResp) 45 else Seq() 46 if (params.isMemAddrIQ) { 47 println(s"[${this.desiredName}] resp: {" + 48 s"og0Resp: ${resps.contains(io.og0Resp)}, " + 49 s"og1Resp: ${resps.contains(io.og1Resp)}, " + 50 s"finalResp: ${io.fromLoad.nonEmpty && resps.contains(io.fromLoad.get.finalIssueResp)}, " + 51 s"loadBorderResp: ${io.fromLoad.nonEmpty && resps.contains(io.fromLoad.get.memAddrIssueResp)}, " + 52 s"memFastResp: ${io.fromMem.nonEmpty && resps.contains(io.fromMem.get.fastResp)}, " + 53 s"memSlowResp: ${io.fromMem.nonEmpty && resps.contains(io.fromMem.get.slowResp)}, " + 54 s"vecLoadBorderResp: ${io.vecLdIn.nonEmpty && resps.contains(io.vecLdIn.get.resp)}, " + 55 s"}" 56 ) 57 } 58 resps.flatten 59 } 60 61 val resps: Vec[Vec[ValidIO[EntryDeqRespBundle]]] = { 62 if (params.inVfSchd) 63 VecInit(io.og0Resp, io.og1Resp, io.og2Resp.get, 0.U.asTypeOf(io.og0Resp)) 64 else 65 VecInit(io.og0Resp, io.og1Resp, 0.U.asTypeOf(io.og0Resp), 0.U.asTypeOf(io.og0Resp)) 66 } 67 68 69 70 //Module 71 val enqEntries = Seq.fill(EnqEntryNum)(Module(EnqEntry(isComp = true)(p, params))) 72 val othersEntriesSimp = Seq.fill(SimpEntryNum)(Module(OthersEntry(isComp = false)(p, params))) 73 val othersEntriesComp = Seq.fill(CompEntryNum)(Module(OthersEntry(isComp = true)(p, params))) 74 val othersEntries = othersEntriesSimp ++ othersEntriesComp 75 val othersTransPolicy = OptionWrapper(params.isAllComp || params.isAllSimp, Module(new EnqPolicy)) 76 val simpTransPolicy = OptionWrapper(params.hasCompAndSimp, Module(new EnqPolicy)) 77 val compTransPolicy = OptionWrapper(params.hasCompAndSimp, Module(new EnqPolicy)) 78 79 //Wire 80 //entries status 81 val entries = Wire(Vec(params.numEntries, ValidIO(new EntryBundle))) 82 val robIdxVec = Wire(Vec(params.numEntries, new RobPtr)) 83 val validVec = Wire(Vec(params.numEntries, Bool())) 84 val canIssueVec = Wire(Vec(params.numEntries, Bool())) 85 val fuTypeVec = Wire(Vec(params.numEntries, FuType())) 86 val isFirstIssueVec = Wire(Vec(params.numEntries, Bool())) 87 val issueTimerVec = Wire(Vec(params.numEntries, UInt(2.W))) 88 val uopIdxVec = OptionWrapper(params.isVecMemIQ, Wire(Vec(params.numEntries, UopIdx()))) 89 //src status 90 val dataSourceVec = Wire(Vec(params.numEntries, Vec(params.numRegSrc, DataSource()))) 91 val loadDependencyVec = Wire(Vec(params.numEntries, Vec(LoadPipelineWidth, UInt(LoadDependencyWidth.W)))) 92 val srcWakeUpL1ExuOHVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, ExuVec())))) 93 //deq sel 94 val deqSelVec = Wire(Vec(params.numEntries, Bool())) 95 val issueRespVec = Wire(Vec(params.numEntries, ValidIO(new EntryDeqRespBundle))) 96 val deqPortIdxWriteVec = Wire(Vec(params.numEntries, UInt(1.W))) 97 val deqPortIdxReadVec = Wire(Vec(params.numEntries, UInt(1.W))) 98 //trans sel 99 val othersEntryEnqReadyVec = Wire(Vec(OthersEntryNum, Bool())) 100 val othersEntryEnqVec = Wire(Vec(OthersEntryNum, Valid(new EntryBundle))) 101 val enqEntryTransVec = Wire(Vec(EnqEntryNum, Valid(new EntryBundle))) 102 val simpEntryTransVec = OptionWrapper(params.hasCompAndSimp, Wire(Vec(SimpEntryNum, Valid(new EntryBundle)))) 103 val compEnqVec = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, Valid(new EntryBundle)))) 104 105 val enqCanTrans2Simp = OptionWrapper(params.hasCompAndSimp, Wire(Bool())) 106 val enqCanTrans2Comp = OptionWrapper(params.hasCompAndSimp, Wire(Bool())) 107 val simpCanTrans2Comp = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, Bool()))) 108 val simpTransSelVec = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, Valid(UInt(SimpEntryNum.W))))) 109 val compTransSelVec = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, Valid(UInt(CompEntryNum.W))))) 110 val finalSimpTransSelVec = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, UInt(SimpEntryNum.W)))) 111 val finalCompTransSelVec = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, UInt(CompEntryNum.W)))) 112 113 val enqCanTrans2Others = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Bool())) 114 val othersTransSelVec = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(EnqEntryNum, Valid(UInt(OthersEntryNum.W))))) 115 val finalOthersTransSelVec = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(EnqEntryNum, UInt(OthersEntryNum.W)))) 116 117 val simpEntryEnqReadyVec = othersEntryEnqReadyVec.take(SimpEntryNum) 118 val compEntryEnqReadyVec = othersEntryEnqReadyVec.takeRight(CompEntryNum) 119 val simpEntryEnqVec = othersEntryEnqVec.take(SimpEntryNum) 120 val compEntryEnqVec = othersEntryEnqVec.takeRight(CompEntryNum) 121 //debug 122 val entryInValidVec = Wire(Vec(params.numEntries, Bool())) 123 val entryOutDeqValidVec = Wire(Vec(params.numEntries, Bool())) 124 val entryOutTransValidVec = Wire(Vec(params.numEntries, Bool())) 125 val perfLdCancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, Bool())))) 126 val perfOg0CancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, Bool())))) 127 val perfWakeupByWBVec = Wire(Vec(params.numEntries, Vec(params.numRegSrc, Bool()))) 128 val perfWakeupByIQVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, Vec(params.numWakeupFromIQ, Bool()))))) 129 //cancel bypass 130 val cancelBypassVec = Wire(Vec(params.numEntries, Bool())) 131 132 133 //enqEntries 134 enqEntries.zipWithIndex.foreach { case (enqEntry, entryIdx) => 135 enqEntry.io.commonIn.enq := io.enq(entryIdx) 136 enqEntry.io.commonIn.transSel := (if (params.isAllComp || params.isAllSimp) enqCanTrans2Others.get && othersTransSelVec.get(entryIdx).valid 137 else enqCanTrans2Simp.get && simpTransSelVec.get(entryIdx).valid || enqCanTrans2Comp.get && compTransSelVec.get(entryIdx).valid) 138 EntriesConnect(enqEntry.io.commonIn, enqEntry.io.commonOut, entryIdx) 139 enqEntry.io.enqDelayIn1.wakeUpFromWB := RegEnable(io.wakeUpFromWB, io.enq(entryIdx).valid) 140 enqEntry.io.enqDelayIn1.wakeUpFromIQ := RegEnable(io.wakeUpFromIQ, io.enq(entryIdx).valid) 141 enqEntry.io.enqDelayIn1.og0Cancel := RegNext(io.og0Cancel.asUInt) 142 enqEntry.io.enqDelayIn1.ldCancel := RegNext(io.ldCancel) 143 // note: these signals with 2 cycle delay should not be enabled by io.enq.valid 144 enqEntry.io.enqDelayIn2.wakeUpFromWB := DelayN(io.wakeUpFromWB, 2) 145 enqEntry.io.enqDelayIn2.wakeUpFromIQ := DelayN(io.wakeUpFromIQ, 2) 146 enqEntry.io.enqDelayIn2.og0Cancel := DelayN(io.og0Cancel.asUInt, 2) 147 enqEntry.io.enqDelayIn2.ldCancel := DelayN(io.ldCancel, 2) 148 enqEntryTransVec(entryIdx) := enqEntry.io.commonOut.transEntry 149 } 150 //othersEntries 151 othersEntries.zipWithIndex.foreach { case (othersEntry, entryIdx) => 152 othersEntry.io.commonIn.enq := othersEntryEnqVec(entryIdx) 153 othersEntry.io.commonIn.transSel := (if (params.hasCompAndSimp && (entryIdx < SimpEntryNum)) 154 io.simpEntryDeqSelVec.get.zip(simpCanTrans2Comp.get).map(x => x._1(entryIdx) && x._2).reduce(_ | _) 155 else false.B) 156 EntriesConnect(othersEntry.io.commonIn, othersEntry.io.commonOut, entryIdx + EnqEntryNum) 157 othersEntryEnqReadyVec(entryIdx) := othersEntry.io.commonOut.enqReady 158 if (params.hasCompAndSimp && (entryIdx < SimpEntryNum)) { 159 simpEntryTransVec.get(entryIdx) := othersEntry.io.commonOut.transEntry 160 } 161 } 162 163 164 deqSelVec.zip(deqPortIdxWriteVec).zipWithIndex.foreach { case ((deqSel, deqPortIdxWrite), i) => 165 val deqVec = io.deqSelOH.zip(io.deqReady).map(x => x._1.valid && x._1.bits(i) && x._2) 166 deqPortIdxWrite := OHToUInt(deqVec) 167 deqSel := deqVec.reduce(_ | _) 168 } 169 170 171 if (params.isAllComp || params.isAllSimp) { 172 //transPolicy 173 othersTransPolicy.get.io.canEnq := othersEntryEnqReadyVec.asUInt 174 175 // we only allow all or none of the enq entries transfering to others entries. 176 enqCanTrans2Others.get := PopCount(validVec.take(EnqEntryNum)) <= PopCount(othersEntryEnqReadyVec) 177 // othersTransSelVec(i) is the target others entry for enq entry [i]. 178 // note that dispatch does not guarantee the validity of enq entries with low index. 179 // that means in some cases enq entry [0] is invalid while enq entry [1] is valid. 180 // in this case, enq entry [1] should use result [0] of TransPolicy. 181 othersTransSelVec.get(0).valid := othersTransPolicy.get.io.enqSelOHVec(0).valid && validVec(0) 182 othersTransSelVec.get(0).bits := othersTransPolicy.get.io.enqSelOHVec(0).bits 183 if (params.numEnq == 2) { 184 othersTransSelVec.get(1).valid := Mux(!validVec(0), othersTransPolicy.get.io.enqSelOHVec(0).valid, othersTransPolicy.get.io.enqSelOHVec(1).valid) 185 othersTransSelVec.get(1).bits := Mux(!validVec(0), othersTransPolicy.get.io.enqSelOHVec(0).bits, othersTransPolicy.get.io.enqSelOHVec(1).bits) 186 } 187 188 finalOthersTransSelVec.get.zip(othersTransSelVec.get).zipWithIndex.foreach { case ((finalOH, selOH), enqIdx) => 189 finalOH := Fill(OthersEntryNum, enqCanTrans2Others.get && selOH.valid) & selOH.bits 190 } 191 192 //othersEntryEnq 193 othersEntryEnqVec.zipWithIndex.foreach { case (othersEntryEnq, othersIdx) => 194 val othersEnqOH = finalOthersTransSelVec.get.map(_(othersIdx)) 195 if (othersEnqOH.size == 1) 196 othersEntryEnq := Mux(othersEnqOH.head, enqEntryTransVec.head, 0.U.asTypeOf(enqEntryTransVec.head)) 197 else 198 othersEntryEnq := Mux1H(othersEnqOH, enqEntryTransVec) 199 } 200 } 201 else { 202 //transPolicy 203 simpTransPolicy.get.io.canEnq := VecInit(simpEntryEnqReadyVec).asUInt 204 compTransPolicy.get.io.canEnq := VecInit(validVec.takeRight(CompEntryNum).map(!_)).asUInt 205 206 // we only allow all or none of the enq entries transfering to comp/simp entries. 207 // when all of simp entries are empty and comp entries are enough, transfer to comp entries. 208 // otherwise, transfer to simp entries. 209 enqCanTrans2Comp.get := PopCount(validVec.take(EnqEntryNum)) <= PopCount(validVec.takeRight(CompEntryNum).map(!_)) && !validVec.drop(EnqEntryNum).take(SimpEntryNum).reduce(_ || _) 210 enqCanTrans2Simp.get := !enqCanTrans2Comp.get && PopCount(validVec.take(EnqEntryNum)) <= PopCount(simpEntryEnqReadyVec) 211 simpCanTrans2Comp.get.zipWithIndex.foreach { case (canTrans, idx) => 212 canTrans := !enqCanTrans2Comp.get && PopCount(validVec.takeRight(CompEntryNum).map(!_)) >= (idx + 1).U 213 } 214 215 // simp/compTransSelVec(i) is the target simp/comp entry for enq entry [i]. 216 // note that dispatch does not guarantee the validity of enq entries with low index. 217 // that means in some cases enq entry [0] is invalid while enq entry [1] is valid. 218 // in this case, enq entry [1] should use result [0] of TransPolicy. 219 simpTransSelVec.get(0).valid := simpTransPolicy.get.io.enqSelOHVec(0).valid && validVec(0) 220 simpTransSelVec.get(0).bits := simpTransPolicy.get.io.enqSelOHVec(0).bits 221 compTransSelVec.get(0).valid := compTransPolicy.get.io.enqSelOHVec(0).valid && validVec(0) 222 compTransSelVec.get(0).bits := compTransPolicy.get.io.enqSelOHVec(0).bits 223 if (params.numEnq == 2) { 224 simpTransSelVec.get(1).valid := Mux(!validVec(0), simpTransPolicy.get.io.enqSelOHVec(0).valid, simpTransPolicy.get.io.enqSelOHVec(1).valid) 225 simpTransSelVec.get(1).bits := Mux(!validVec(0), simpTransPolicy.get.io.enqSelOHVec(0).bits, simpTransPolicy.get.io.enqSelOHVec(1).bits) 226 compTransSelVec.get(1).valid := Mux(!validVec(0), compTransPolicy.get.io.enqSelOHVec(0).valid, compTransPolicy.get.io.enqSelOHVec(1).valid) 227 compTransSelVec.get(1).bits := Mux(!validVec(0), compTransPolicy.get.io.enqSelOHVec(0).bits, compTransPolicy.get.io.enqSelOHVec(1).bits) 228 } 229 230 finalSimpTransSelVec.get.zip(simpTransSelVec.get).zipWithIndex.foreach { case ((finalOH, selOH), enqIdx) => 231 finalOH := Fill(SimpEntryNum, enqCanTrans2Simp.get && selOH.valid) & selOH.bits 232 } 233 finalCompTransSelVec.get.zip(compTransSelVec.get).zip(compTransPolicy.get.io.enqSelOHVec).zipWithIndex.foreach { 234 case (((finalOH, selOH), origSelOH), enqIdx) => 235 finalOH := Mux(enqCanTrans2Comp.get, Fill(CompEntryNum, selOH.valid) & selOH.bits, Fill(CompEntryNum, origSelOH.valid) & origSelOH.bits) 236 } 237 238 //othersEntryEnq 239 simpEntryEnqVec.zipWithIndex.foreach { case (simpEntryEnq, simpIdx) => 240 val simpEnqOH = finalSimpTransSelVec.get.map(_(simpIdx)) 241 // shit Mux1H directly returns in(0) if the seq has only 1 elements 242 if (simpEnqOH.size == 1) 243 simpEntryEnq := Mux(simpEnqOH.head, enqEntryTransVec.head, 0.U.asTypeOf(enqEntryTransVec.head)) 244 else 245 simpEntryEnq := Mux1H(simpEnqOH, enqEntryTransVec) 246 } 247 248 compEnqVec.get.zip(enqEntryTransVec).zip(io.simpEntryDeqSelVec.get).foreach { case ((compEnq, enqEntry), deqSel) => 249 compEnq := Mux(enqCanTrans2Comp.get, enqEntry, Mux1H(deqSel, simpEntryTransVec.get)) 250 } 251 compEntryEnqVec.zipWithIndex.foreach { case (compEntryEnq, compIdx) => 252 val compEnqOH = finalCompTransSelVec.get.map(_(compIdx)) 253 // shit Mux1H directly returns in(0) if the seq has only 1 elements 254 if (compEnqOH.size == 1) 255 compEntryEnq := Mux(compEnqOH.head, compEnqVec.get.head, 0.U.asTypeOf(compEnqVec.get.head)) 256 else 257 compEntryEnq := Mux1H(compEnqOH, compEnqVec.get) 258 } 259 260 assert(PopCount(simpEntryEnqVec.map(_.valid)) <= params.numEnq.U, "the number of simpEntryEnq is more than numEnq\n") 261 assert(PopCount(compEntryEnqVec.map(_.valid)) <= params.numEnq.U, "the number of compEntryEnq is more than numEnq\n") 262 } 263 264 if(backendParams.debugEn) { 265 dontTouch(othersEntryEnqVec) 266 } 267 268 //issueRespVec 269 if (params.isVecMemIQ) { 270 // vector memory IQ 271 issueRespVec.lazyZip(robIdxVec.lazyZip(uopIdxVec.get)).lazyZip(issueTimerVec.lazyZip(deqPortIdxReadVec)).foreach { case (issueResp, (robIdx, uopIdx), (issueTimer, deqPortIdx)) => 272 val respInDatapath = resps(issueTimer(0))(deqPortIdx) 273 val respAfterDatapath = Wire(chiselTypeOf(respInDatapath)) 274 val hitRespsVec = VecInit(memEtyResps.map(x => 275 x.valid && x.bits.robIdx === robIdx && x.bits.uopIdx.get === uopIdx 276 ).toSeq) 277 respAfterDatapath.valid := hitRespsVec.reduce(_ | _) 278 respAfterDatapath.bits := (if (memEtyResps.size == 1) memEtyResps.head.bits 279 else Mux1H(hitRespsVec, memEtyResps.map(_.bits).toSeq)) 280 issueResp := Mux(issueTimer(1), respAfterDatapath, respInDatapath) 281 } 282 } else if (params.isMemAddrIQ) { 283 // scalar memory IQ 284 issueRespVec.lazyZip(robIdxVec).lazyZip(issueTimerVec.lazyZip(deqPortIdxReadVec)).foreach { case (issueResp, robIdx, (issueTimer, deqPortIdx)) => 285 val respInDatapath = resps(issueTimer(0))(deqPortIdx) 286 val respAfterDatapath = Wire(chiselTypeOf(respInDatapath)) 287 val hitRespsVec = VecInit(memEtyResps.map(x => x.valid && (x.bits.robIdx === robIdx)).toSeq) 288 respAfterDatapath.valid := hitRespsVec.reduce(_ | _) 289 respAfterDatapath.bits := (if (memEtyResps.size == 1) memEtyResps.head.bits 290 else Mux1H(hitRespsVec, memEtyResps.map(_.bits).toSeq)) 291 issueResp := Mux(issueTimer(1), respAfterDatapath, respInDatapath) 292 } 293 } 294 else { 295 issueRespVec.lazyZip(issueTimerVec.lazyZip(deqPortIdxReadVec)).foreach { case (issueResp, (issueTimer, deqPortIdx)) => 296 val Resp = resps(issueTimer)(deqPortIdx) 297 issueResp := Resp 298 } 299 } 300 301 //deq 302 val enqEntryOldest = Wire(Vec(params.numDeq, ValidIO(new EntryBundle))) 303 val simpEntryOldest = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle)))) 304 val compEntryOldest = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle)))) 305 val othersEntryOldest = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle)))) 306 val enqEntryOldestCancel = Wire(Vec(params.numDeq, Bool())) 307 val simpEntryOldestCancel = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, Bool()))) 308 val compEntryOldestCancel = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, Bool()))) 309 val othersEntryOldestCancel = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(params.numDeq, Bool()))) 310 311 io.enqEntryOldestSel.zipWithIndex.map { case (sel, deqIdx) => 312 enqEntryOldest(deqIdx) := Mux1H(sel.bits, entries.take(EnqEntryNum)) 313 enqEntryOldestCancel(deqIdx) := Mux1H(sel.bits, cancelBypassVec.take(EnqEntryNum)) 314 } 315 316 if (params.isAllComp || params.isAllSimp) { 317 io.othersEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) => 318 othersEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum)) 319 othersEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum)) 320 } 321 } 322 else { 323 io.simpEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) => 324 simpEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum).take(SimpEntryNum)) 325 simpEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum).take(SimpEntryNum)) 326 } 327 io.compEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) => 328 compEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum).takeRight(CompEntryNum)) 329 compEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum).takeRight(CompEntryNum)) 330 } 331 } 332 333 if (params.deqFuSame) { 334 val subDeqPolicyEntryVec = Wire(Vec(params.numDeq, ValidIO(new EntryBundle))) 335 val subDeqPolicyValidVec = Wire(Vec(params.numDeq, Bool())) 336 val subDeqPolicyCancelBypassVec = Wire(Vec(params.numDeq, Bool())) 337 338 subDeqPolicyValidVec(0) := PopCount(io.subDeqRequest.get(0)) >= 1.U 339 subDeqPolicyValidVec(1) := PopCount(io.subDeqRequest.get(0)) >= 2.U 340 341 if (params.isAllComp || params.isAllSimp) { 342 subDeqPolicyEntryVec(0) := PriorityMux(io.subDeqRequest.get(0), entries) 343 subDeqPolicyEntryVec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), entries.reverse) 344 subDeqPolicyCancelBypassVec(0) := PriorityMux(io.subDeqRequest.get(0), cancelBypassVec) 345 subDeqPolicyCancelBypassVec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), cancelBypassVec.reverse) 346 347 io.deqEntry(0) := Mux(io.othersEntryOldestSel.get(0).valid, othersEntryOldest.get(0), subDeqPolicyEntryVec(1)) 348 io.deqEntry(1) := subDeqPolicyEntryVec(0) 349 io.cancelDeqVec(0) := Mux(io.othersEntryOldestSel.get(0).valid, othersEntryOldestCancel.get(0), subDeqPolicyCancelBypassVec(1)) 350 io.cancelDeqVec(1) := subDeqPolicyCancelBypassVec(0) 351 } 352 else { 353 subDeqPolicyEntryVec(0) := PriorityMux(Reverse(io.subDeqRequest.get(0)), entries.reverse) 354 subDeqPolicyEntryVec(1) := PriorityMux(io.subDeqRequest.get(0), entries) 355 subDeqPolicyCancelBypassVec(0) := PriorityMux(Reverse(io.subDeqRequest.get(0)), cancelBypassVec.reverse) 356 subDeqPolicyCancelBypassVec(1) := PriorityMux(io.subDeqRequest.get(0), cancelBypassVec) 357 358 io.deqEntry(0) := Mux(io.compEntryOldestSel.get(0).valid, 359 compEntryOldest.get(0), 360 Mux(io.simpEntryOldestSel.get(0).valid, simpEntryOldest.get(0), subDeqPolicyEntryVec(1))) 361 io.deqEntry(1) := subDeqPolicyEntryVec(0) 362 io.cancelDeqVec(0) := Mux(io.compEntryOldestSel.get(0).valid, 363 compEntryOldestCancel.get(0), 364 Mux(io.simpEntryOldestSel.get(0).valid, simpEntryOldestCancel.get(0), subDeqPolicyCancelBypassVec(1))) 365 io.cancelDeqVec(1) := subDeqPolicyCancelBypassVec(0) 366 } 367 368 when (subDeqPolicyValidVec(0)) { 369 assert(Mux1H(io.subDeqSelOH.get(0), entries).bits.status.robIdx === subDeqPolicyEntryVec(0).bits.status.robIdx, "subDeqSelOH(0) is not the same\n") 370 } 371 when (subDeqPolicyValidVec(1)) { 372 assert(Mux1H(io.subDeqSelOH.get(1), entries).bits.status.robIdx === subDeqPolicyEntryVec(1).bits.status.robIdx, "subDeqSelOH(1) is not the same\n") 373 } 374 } 375 else { 376 if (params.isAllComp || params.isAllSimp) { 377 io.othersEntryOldestSel.get.zipWithIndex.foreach { case (sel, i) => 378 io.deqEntry(i) := Mux(sel.valid, othersEntryOldest.get(i), enqEntryOldest(i)) 379 io.cancelDeqVec(i) := Mux(sel.valid, othersEntryOldestCancel.get(i), enqEntryOldestCancel(i)) 380 } 381 } 382 else { 383 io.compEntryOldestSel.get.zip(io.simpEntryOldestSel.get).zipWithIndex.foreach { case ((compSel, simpSel), i) => 384 io.deqEntry(i) := Mux(compSel.valid, 385 compEntryOldest.get(i), 386 Mux(simpSel.valid, simpEntryOldest.get(i), enqEntryOldest(i))) 387 io.cancelDeqVec(i) := Mux(compSel.valid, 388 compEntryOldestCancel.get(i), 389 Mux(simpSel.valid, simpEntryOldestCancel.get(i), enqEntryOldestCancel(i))) 390 } 391 } 392 } 393 394 io.valid := validVec.asUInt 395 io.canIssue := canIssueVec.asUInt 396 io.fuType := fuTypeVec 397 io.dataSources := dataSourceVec 398 io.srcWakeUpL1ExuOH.foreach(_ := srcWakeUpL1ExuOHVec.get) 399 io.loadDependency := loadDependencyVec 400 io.isFirstIssue.zipWithIndex.foreach{ case (isFirstIssue, deqIdx) => 401 isFirstIssue := io.deqSelOH(deqIdx).valid && Mux1H(io.deqSelOH(deqIdx).bits, isFirstIssueVec) 402 } 403 io.simpEntryEnqSelVec.foreach(_ := finalSimpTransSelVec.get.zip(enqEntryTransVec).map(x => x._1 & Fill(SimpEntryNum, x._2.valid))) 404 io.compEntryEnqSelVec.foreach(_ := finalCompTransSelVec.get.zip(compEnqVec.get).map(x => x._1 & Fill(CompEntryNum, x._2.valid))) 405 io.othersEntryEnqSelVec.foreach(_ := finalOthersTransSelVec.get.zip(enqEntryTransVec).map(x => x._1 & Fill(OthersEntryNum, x._2.valid))) 406 io.robIdx.foreach(_ := robIdxVec) 407 io.uopIdx.foreach(_ := uopIdxVec.get) 408 409 410 def EntriesConnect(in: CommonInBundle, out: CommonOutBundle, entryIdx: Int) = { 411 in.flush := io.flush 412 in.wakeUpFromWB := io.wakeUpFromWB 413 in.wakeUpFromIQ := io.wakeUpFromIQ 414 in.vlIsZero := io.vlIsZero 415 in.vlIsVlmax := io.vlIsVlmax 416 in.og0Cancel := io.og0Cancel 417 in.og1Cancel := io.og1Cancel 418 in.ldCancel := io.ldCancel 419 in.deqSel := deqSelVec(entryIdx) 420 in.deqPortIdxWrite := deqPortIdxWriteVec(entryIdx) 421 in.issueResp := issueRespVec(entryIdx) 422 if (params.isVecMemIQ) { 423 in.fromLsq.get.sqDeqPtr := io.vecMemIn.get.sqDeqPtr 424 in.fromLsq.get.lqDeqPtr := io.vecMemIn.get.lqDeqPtr 425 } 426 validVec(entryIdx) := out.valid 427 canIssueVec(entryIdx) := out.canIssue 428 fuTypeVec(entryIdx) := out.fuType 429 robIdxVec(entryIdx) := out.robIdx 430 dataSourceVec(entryIdx) := out.dataSource 431 isFirstIssueVec(entryIdx) := out.isFirstIssue 432 entries(entryIdx) := out.entry 433 deqPortIdxReadVec(entryIdx) := out.deqPortIdxRead 434 issueTimerVec(entryIdx) := out.issueTimerRead 435 loadDependencyVec(entryIdx) := out.entry.bits.status.mergedLoadDependency 436 cancelBypassVec(entryIdx) := out.cancelBypass 437 if (params.hasIQWakeUp) { 438 srcWakeUpL1ExuOHVec.get(entryIdx) := out.srcWakeUpL1ExuOH.get 439 } 440 if (params.isVecMemIQ) { 441 uopIdxVec.get(entryIdx) := out.uopIdx.get 442 } 443 entryInValidVec(entryIdx) := out.entryInValid 444 entryOutDeqValidVec(entryIdx) := out.entryOutDeqValid 445 entryOutTransValidVec(entryIdx) := out.entryOutTransValid 446 perfWakeupByWBVec(entryIdx) := out.perfWakeupByWB 447 if (params.hasIQWakeUp) { 448 perfLdCancelVec.get(entryIdx) := out.perfLdCancel.get 449 perfOg0CancelVec.get(entryIdx) := out.perfOg0Cancel.get 450 perfWakeupByIQVec.get(entryIdx) := out.perfWakeupByIQ.get 451 } 452 } 453 454 io.vecLdIn.foreach(dontTouch(_)) 455 456 // entries perf counter 457 // enq 458 for (i <- 0 until params.numEnq) { 459 XSPerfAccumulate(s"enqEntry_${i}_in_cnt", entryInValidVec(i)) 460 XSPerfAccumulate(s"enqEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i)) 461 XSPerfAccumulate(s"enqEntry_${i}_out_trans_cnt", entryOutTransValidVec(i)) 462 } 463 // simple 464 for (i <- 0 until params.numSimp) { 465 XSPerfAccumulate(s"simpEntry_${i}_in_cnt", entryInValidVec(i + params.numEnq)) 466 XSPerfAccumulate(s"simpEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i + params.numEnq)) 467 XSPerfAccumulate(s"simpEntry_${i}_out_trans_cnt", entryOutTransValidVec(i + params.numEnq)) 468 } 469 // complex 470 for (i <- 0 until params.numComp) { 471 XSPerfAccumulate(s"compEntry_${i}_in_cnt", entryInValidVec(i + params.numEnq + params.numSimp)) 472 XSPerfAccumulate(s"compEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i + params.numEnq + params.numSimp)) 473 XSPerfAccumulate(s"compEntry_${i}_out_trans_cnt", entryOutTransValidVec(i + params.numEnq + params.numSimp)) 474 } 475 // total 476 XSPerfAccumulate(s"enqEntry_all_in_cnt", PopCount(entryInValidVec.take(params.numEnq))) 477 XSPerfAccumulate(s"enqEntry_all_out_deq_cnt", PopCount(entryOutDeqValidVec.take(params.numEnq))) 478 XSPerfAccumulate(s"enqEntry_all_out_trans_cnt", PopCount(entryOutTransValidVec.take(params.numEnq))) 479 for (srcIdx <- 0 until params.numRegSrc) { 480 XSPerfAccumulate(s"enqEntry_all_wakeup_wb_src${srcIdx}_cnt", PopCount(perfWakeupByWBVec.take(params.numEnq).map(_(srcIdx)))) 481 if (params.hasIQWakeUp) { 482 XSPerfAccumulate(s"enqEntry_all_ldCancel_src${srcIdx}_cnt", PopCount(perfLdCancelVec.get.take(params.numEnq).map(_(srcIdx)))) 483 XSPerfAccumulate(s"enqEntry_all_og0Cancel_src${srcIdx}_cnt", PopCount(perfOg0CancelVec.get.take(params.numEnq).map(_(srcIdx)))) 484 for (iqIdx <- 0 until params.numWakeupFromIQ) { 485 XSPerfAccumulate(s"enqEntry_all_wakeup_iq_from_exu${params.wakeUpSourceExuIdx(iqIdx)}_src${srcIdx}_cnt", PopCount(perfWakeupByIQVec.get.take(params.numEnq).map(_(srcIdx)(iqIdx)))) 486 } 487 } 488 } 489 490 XSPerfAccumulate(s"othersEntry_all_in_cnt", PopCount(entryInValidVec.drop(params.numEnq))) 491 XSPerfAccumulate(s"othersEntry_all_out_deq_cnt", PopCount(entryOutDeqValidVec.drop(params.numEnq))) 492 XSPerfAccumulate(s"othersEntry_all_out_trans_cnt", PopCount(entryOutTransValidVec.drop(params.numEnq))) 493 494 for (srcIdx <- 0 until params.numRegSrc) { 495 XSPerfAccumulate(s"othersEntry_all_wakeup_wb_src${srcIdx}_cnt", PopCount(perfWakeupByWBVec.drop(params.numEnq).map(_(srcIdx)))) 496 if (params.hasIQWakeUp) { 497 XSPerfAccumulate(s"othersEntry_all_ldCancel_src${srcIdx}_cnt", PopCount(perfLdCancelVec.get.drop(params.numEnq).map(_(srcIdx)))) 498 XSPerfAccumulate(s"othersEntry_all_og0Cancel_src${srcIdx}_cnt", PopCount(perfOg0CancelVec.get.drop(params.numEnq).map(_(srcIdx)))) 499 for (iqIdx <- 0 until params.numWakeupFromIQ) { 500 XSPerfAccumulate(s"othersEntry_all_wakeup_iq_from_exu${params.wakeUpSourceExuIdx(iqIdx)}_src${srcIdx}_cnt", PopCount(perfWakeupByIQVec.get.drop(params.numEnq).map(_(srcIdx)(iqIdx)))) 501 } 502 } 503 } 504 505 for (t <- FuType.functionNameMap.keys) { 506 val fuName = FuType.functionNameMap(t) 507 if (params.getFuCfgs.map(_.fuType == t).reduce(_ | _) && params.getFuCfgs.size > 1) { 508 for (srcIdx <- 0 until params.numRegSrc) { 509 XSPerfAccumulate(s"allEntry_futype_${fuName}_wakeup_wb_src${srcIdx}_cnt", PopCount(perfWakeupByWBVec.zip(fuTypeVec).map{ case(x, fu) => x(srcIdx) && fu(t.id) })) 510 if (params.hasIQWakeUp) { 511 XSPerfAccumulate(s"allEntry_futype_${fuName}_ldCancel_src${srcIdx}_cnt", PopCount(perfLdCancelVec.get.zip(fuTypeVec).map{ case(x, fu) => x(srcIdx) && fu(t.id) })) 512 XSPerfAccumulate(s"allEntry_futype_${fuName}_og0Cancel_src${srcIdx}_cnt", PopCount(perfOg0CancelVec.get.zip(fuTypeVec).map{ case(x, fu) => x(srcIdx) && fu(t.id) })) 513 for (iqIdx <- 0 until params.numWakeupFromIQ) { 514 XSPerfAccumulate(s"allEntry_futype_${fuName}_wakeup_iq_from_exu${params.wakeUpSourceExuIdx(iqIdx)}_src${srcIdx}_cnt", PopCount(perfWakeupByIQVec.get.zip(fuTypeVec).map{ case(x, fu) => x(srcIdx)(iqIdx) && fu(t.id) })) 515 } 516 } 517 } 518 } 519 } 520} 521 522class EntriesIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle { 523 val flush = Flipped(ValidIO(new Redirect)) 524 //enq 525 val enq = Vec(params.numEnq, Flipped(ValidIO(new EntryBundle))) 526 val og0Resp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 527 val og1Resp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 528 val og2Resp = OptionWrapper(params.inVfSchd, Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))) 529 //deq sel 530 val deqReady = Vec(params.numDeq, Input(Bool())) 531 val deqSelOH = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEntries.W)))) 532 val enqEntryOldestSel = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEnq.W)))) 533 val simpEntryOldestSel = OptionWrapper(params.hasCompAndSimp, Vec(params.numDeq, Flipped(ValidIO(UInt(params.numSimp.W))))) 534 val compEntryOldestSel = OptionWrapper(params.hasCompAndSimp, Vec(params.numDeq, Flipped(ValidIO(UInt(params.numComp.W))))) 535 val othersEntryOldestSel= OptionWrapper(params.isAllComp || params.isAllSimp, Vec(params.numDeq, Flipped(ValidIO(UInt((params.numEntries - params.numEnq).W))))) 536 val subDeqRequest = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W)))) 537 val subDeqSelOH = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W)))) 538 // wakeup 539 val wakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle) 540 val wakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle) 541 val vlIsZero = Input(Bool()) 542 val vlIsVlmax = Input(Bool()) 543 val og0Cancel = Input(ExuOH(backendParams.numExu)) 544 val og1Cancel = Input(ExuOH(backendParams.numExu)) 545 val ldCancel = Vec(backendParams.LdExuCnt, Flipped(new LoadCancelIO)) 546 //entries status 547 val valid = Output(UInt(params.numEntries.W)) 548 val canIssue = Output(UInt(params.numEntries.W)) 549 val fuType = Vec(params.numEntries, Output(FuType())) 550 val dataSources = Vec(params.numEntries, Vec(params.numRegSrc, Output(DataSource()))) 551 val loadDependency = Vec(params.numEntries, Vec(LoadPipelineWidth, UInt(LoadDependencyWidth.W))) 552 val srcWakeUpL1ExuOH = OptionWrapper(params.hasIQWakeUp, Vec(params.numEntries, Vec(params.numRegSrc, Output(ExuVec())))) 553 //deq status 554 val isFirstIssue = Vec(params.numDeq, Output(Bool())) 555 val deqEntry = Vec(params.numDeq, ValidIO(new EntryBundle)) 556 val cancelDeqVec = Vec(params.numDeq, Output(Bool())) 557 558 // load/hybird only 559 val fromLoad = OptionWrapper(params.isLdAddrIQ || params.isHyAddrIQ, new Bundle { 560 val finalIssueResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 561 val memAddrIssueResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 562 }) 563 // mem only 564 val fromMem = OptionWrapper(params.isMemAddrIQ, new Bundle { 565 val slowResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 566 val fastResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 567 }) 568 // vec mem only 569 val vecMemIn = OptionWrapper(params.isVecMemIQ, new Bundle { 570 val sqDeqPtr = Input(new SqPtr) 571 val lqDeqPtr = Input(new LqPtr) 572 }) 573 val vecLdIn = OptionWrapper(params.isVecLduIQ, new Bundle { 574 val resp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 575 }) 576 val robIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, new RobPtr))) 577 val uopIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, UopIdx()))) 578 579 // trans 580 val simpEntryDeqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Input(UInt(params.numSimp.W)))) 581 val simpEntryEnqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Output(UInt(params.numSimp.W)))) 582 val compEntryEnqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Output(UInt(params.numComp.W)))) 583 val othersEntryEnqSelVec = OptionWrapper(params.isAllComp || params.isAllSimp, Vec(params.numEnq, Output(UInt((params.numEntries - params.numEnq).W)))) 584 585 def wakeup = wakeUpFromWB ++ wakeUpFromIQ 586} 587