1package xiangshan.backend.issue 2 3import org.chipsalliance.cde.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import utility.HasCircularQueuePtrHelper 7import utils.{MathUtils, OptionWrapper, XSError} 8import xiangshan._ 9import xiangshan.backend.Bundles._ 10import xiangshan.backend.datapath.DataConfig.VAddrData 11import xiangshan.backend.datapath.DataSource 12import xiangshan.backend.fu.FuType 13import xiangshan.backend.fu.vector.Utils.NOnes 14import xiangshan.backend.rob.RobPtr 15import xiangshan.mem.{LqPtr, MemWaitUpdateReq, SqPtr} 16import xiangshan.backend.issue.EntryBundles._ 17 18class Entries(implicit p: Parameters, params: IssueBlockParams) extends XSModule { 19 override def desiredName: String = params.getEntryName 20 21 require(params.numEnq <= 2, "number of enq should be no more than 2") 22 23 private val EnqEntryNum = params.numEnq 24 private val OthersEntryNum = params.numEntries - params.numEnq 25 val io = IO(new EntriesIO) 26 27 // only memAddrIQ use it 28 val memEtyResps: MixedVec[ValidIO[EntryDeqRespBundle]] = { 29 if (params.isLdAddrIQ && !params.isStAddrIQ) 30 MixedVecInit(io.og0Resp ++ io.og1Resp ++ io.finalIssueResp.get) 31 else if (params.isLdAddrIQ && params.isStAddrIQ || params.isHyAddrIQ) 32 MixedVecInit(io.og0Resp ++ io.og1Resp ++ io.finalIssueResp.get ++ io.fromMem.get.fastResp ++ io.fromMem.get.slowResp) 33 else if (params.isMemAddrIQ) 34 MixedVecInit(io.og0Resp ++ io.og1Resp ++ io.fromMem.get.fastResp ++ io.fromMem.get.slowResp) 35 else MixedVecInit(Seq()) 36 } 37 38 val resps: Vec[Vec[ValidIO[EntryDeqRespBundle]]] = VecInit(io.og0Resp, io.og1Resp, 0.U.asTypeOf(io.og0Resp), 0.U.asTypeOf(io.og0Resp)) 39 40 //Module 41 val enqEntries = Seq.fill(EnqEntryNum)(Module(EnqEntry(isComp = true)(p, params))) 42 val othersEntries = Seq.fill(OthersEntryNum)(Module(OthersEntry(isComp = true)(p, params))) 43 val transPolicy = Module(new EnqPolicy) 44 45 //Wire 46 //entries status 47 val entries = Wire(Vec(params.numEntries, ValidIO(new EntryBundle))) 48 val robIdxVec = Wire(Vec(params.numEntries, new RobPtr)) 49 val validVec = Wire(Vec(params.numEntries, Bool())) 50 val canIssueVec = Wire(Vec(params.numEntries, Bool())) 51 val fuTypeVec = Wire(Vec(params.numEntries, FuType())) 52 val isFirstIssueVec = Wire(Vec(params.numEntries, Bool())) 53 val issueTimerVec = Wire(Vec(params.numEntries, UInt(2.W))) 54 //src status 55 val dataSourceVec = Wire(Vec(params.numEntries, Vec(params.numRegSrc, DataSource()))) 56 val srcTimerVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, UInt(3.W))))) 57 val srcWakeUpL1ExuOHVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, ExuVec())))) 58 val srcLoadDependencyVec= OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, Vec(LoadPipelineWidth, UInt(3.W)))))) 59 val loadDependencyVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(LoadPipelineWidth, UInt(3.W))))) 60 //deq sel 61 val deqSelVec = Wire(Vec(params.numEntries, Bool())) 62 val issueRespVec = Wire(Vec(params.numEntries, ValidIO(new EntryDeqRespBundle))) 63 val deqPortIdxWriteVec = Wire(Vec(params.numEntries, UInt(1.W))) 64 val deqPortIdxReadVec = Wire(Vec(params.numEntries, UInt(1.W))) 65 //trans sel 66 val transSelVec = Wire(Vec(EnqEntryNum, Vec(OthersEntryNum, Bool()))) 67 val transEntryDeqVec = Wire(Vec(EnqEntryNum, ValidIO(new EntryBundle))) 68 val transEntryEnqVec = Wire(Vec(OthersEntryNum, ValidIO(new EntryBundle))) 69 //debug 70 val cancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Bool()))) 71 //cancel bypass 72 val cancelBypassVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Bool()))) 73 val uopIdxVec = OptionWrapper(params.isVecMemIQ, Wire(Vec(params.numEntries, UopIdx()))) 74 75 val canTrans = Wire(Bool()) 76 val enqReadyOthersVec = Wire(Vec(OthersEntryNum, Bool())) 77 val enqTransSelVec = Wire(Vec(EnqEntryNum, Valid(UInt(OthersEntryNum.W)))) 78 79 io.transEntryDeqVec := transEntryDeqVec 80 81 //enqEntries 82 enqEntries.zipWithIndex.foreach { case (enqEntry, entryIdx) => 83 enqEntry.io.commonIn.enq := io.enq(entryIdx) 84 enqEntry.io.commonIn.transSel := canTrans && enqTransSelVec(entryIdx).valid 85 EntriesConnect(enqEntry.io.commonIn, enqEntry.io.commonOut, entryIdx) 86 enqEntry.io.enqDelayWakeUpFromWB := RegNext(io.wakeUpFromWB) 87 enqEntry.io.enqDelayWakeUpFromIQ := RegNext(io.wakeUpFromIQ) 88 enqEntry.io.enqDelayOg0Cancel := RegNext(io.og0Cancel.asUInt) 89 enqEntry.io.enqDelayLdCancel := RegNext(io.ldCancel) 90 transEntryDeqVec(entryIdx) := enqEntry.io.commonOut.transEntry 91 // TODO: move it into EntriesConnect 92 if (params.isVecMemIQ) { 93 enqEntry.io.commonIn.fromLsq.get.sqDeqPtr := io.vecMemIn.get.sqDeqPtr 94 enqEntry.io.commonIn.fromLsq.get.lqDeqPtr := io.vecMemIn.get.lqDeqPtr 95 } 96 } 97 //othersEntries 98 othersEntries.zipWithIndex.foreach { case (othersEntry, entryIdx) => 99 othersEntry.io.commonIn.enq := transEntryEnqVec(entryIdx) 100 EntriesConnect(othersEntry.io.commonIn, othersEntry.io.commonOut, entryIdx + EnqEntryNum) 101 othersEntry.io.commonIn.transSel := transSelVec.map(x => x(entryIdx)).reduce(_ | _) 102 enqReadyOthersVec(entryIdx) := othersEntry.io.commonOut.enqReady 103 if (params.isVecMemIQ) { 104 othersEntry.io.commonIn.fromLsq.get.sqDeqPtr := io.vecMemIn.get.sqDeqPtr 105 othersEntry.io.commonIn.fromLsq.get.lqDeqPtr := io.vecMemIn.get.lqDeqPtr 106 } 107 } 108 109 110 deqSelVec.zip(deqPortIdxWriteVec).zipWithIndex.foreach { case ((deqSel, deqPortIdxWrite), i) => 111 val deqVec = io.deqSelOH.zip(io.deqReady).map(x => x._1.valid && x._1.bits(i) && x._2) 112 deqPortIdxWrite := OHToUInt(deqVec) 113 deqSel := deqVec.reduce(_ | _) 114 } 115 116 117 //transPolicy 118 transPolicy.io.canEnq := enqReadyOthersVec.asUInt 119 canTrans := PopCount(validVec.take(EnqEntryNum)) <= PopCount(enqReadyOthersVec) 120 enqTransSelVec(0).valid := transPolicy.io.enqSelOHVec(0).valid 121 enqTransSelVec(0).bits := transPolicy.io.enqSelOHVec(0).bits 122 // Todo: comments why enqTransSelVec(1).valid relies on validVec(0) 123 if (params.numEnq == 2) { 124 enqTransSelVec(1).valid := Mux(!validVec(0), transPolicy.io.enqSelOHVec(0).valid, transPolicy.io.enqSelOHVec(1).valid) 125 enqTransSelVec(1).bits := Mux(!validVec(0), transPolicy.io.enqSelOHVec(0).bits, transPolicy.io.enqSelOHVec(1).bits) 126 } 127 128 transSelVec.zip(enqTransSelVec).zipWithIndex.foreach { case ((selBools, selOH), enqIdx) => 129 selBools.zipWithIndex.foreach { case (selBool, othersIdx) => 130 selBool := canTrans && validVec(enqIdx) && selOH.valid && selOH.bits(othersIdx) 131 } 132 } 133 134 //transEntryEnq 135 transEntryEnqVec.zipWithIndex.foreach { case (transEntryEnq, othersIdx) => 136 val transEnqHit = transSelVec.map(x => x(othersIdx)) 137 transEntryEnq := Mux1H(transEnqHit, transEntryDeqVec) 138 } 139 if(backendParams.debugEn) { 140 dontTouch(transEntryEnqVec) 141 } 142 143 //issueRespVec 144 if (params.isVecMemIQ) { 145 // vector memory IQ 146 issueRespVec.zip(robIdxVec).zip(uopIdxVec.get).foreach { case ((issueResp, robIdx), uopIdx) => 147 val hitRespsVec = VecInit(resps.flatten.map(x => 148 x.valid && x.bits.robIdx === robIdx && x.bits.uopIdx.get === uopIdx 149 )) 150 issueResp.valid := hitRespsVec.reduce(_ | _) 151 issueResp.bits := Mux1H(hitRespsVec, resps.flatten.map(_.bits)) 152 } 153 } else if (params.isMemAddrIQ) { 154 // scalar memory IQ 155 issueRespVec.zip(robIdxVec).foreach { case (issueResp, robIdx) => 156 val hitRespsVec = VecInit(memEtyResps.map(x => x.valid && (x.bits.robIdx === robIdx)).toSeq) 157 issueResp.valid := hitRespsVec.reduce(_ | _) 158 issueResp.bits := Mux1H(hitRespsVec, memEtyResps.map(_.bits).toSeq) 159 } 160 } 161 else { 162 issueRespVec.zip(issueTimerVec).zip(deqPortIdxReadVec).foreach { case ((issueResp, issueTimer), deqPortIdx) => 163 val Resp = resps(issueTimer)(deqPortIdx) 164 issueResp := Resp 165 } 166 } 167 168 //deq 169 val enqEntryOldest = io.enqEntryOldestSel.map { x => 170 Mux1H(x.bits, entries.take(EnqEntryNum)) 171 } 172 val enqEntryOldestCancel = io.enqEntryOldestSel.map { x => 173 Mux1H(x.bits, cancelBypassVec.getOrElse(VecInit(Seq.fill(params.numEntries)(false.B))).take(EnqEntryNum)) 174 } 175 val othersEntryOldest = io.othersEntryOldestSel.map { x => 176 Mux1H(x.bits, entries.drop(EnqEntryNum)) 177 } 178 val othersEntryOldestCancel = io.othersEntryOldestSel.map { x => 179 Mux1H(x.bits, cancelBypassVec.getOrElse(VecInit(Seq.fill(params.numEntries)(false.B))).drop(EnqEntryNum)) 180 } 181 182 if (params.deqFuSame) { 183 val subDeqPolicyEntryVec = Wire(Vec(params.numDeq, ValidIO(new EntryBundle))) 184 val subDeqPolicyValidVec = Wire(Vec(params.numDeq, Bool())) 185 val subDeqPolicyCancelBypassVec = Wire(Vec(params.numDeq, Bool())) 186 187 subDeqPolicyEntryVec(0) := PriorityMux(io.subDeqRequest.get(0), entries) 188 subDeqPolicyEntryVec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), entries.reverse) 189 subDeqPolicyValidVec(0) := PopCount(io.subDeqRequest.get(0)) >= 1.U 190 subDeqPolicyValidVec(1) := PopCount(io.subDeqRequest.get(0)) >= 2.U 191 subDeqPolicyCancelBypassVec(0) := PriorityMux(io.subDeqRequest.get(0), cancelBypassVec.getOrElse(VecInit(Seq.fill(params.numEntries)(false.B)))) 192 subDeqPolicyCancelBypassVec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), cancelBypassVec.getOrElse(VecInit(Seq.fill(params.numEntries)(false.B))).reverse) 193 194 io.deqEntry(0) := Mux(io.othersEntryOldestSel(0).valid, othersEntryOldest(0), subDeqPolicyEntryVec(1)) 195 io.deqEntry(1) := subDeqPolicyEntryVec(0) 196 io.cancelDeqVec(0) := Mux(io.othersEntryOldestSel(0).valid, othersEntryOldestCancel(0), subDeqPolicyCancelBypassVec(1)) 197 io.cancelDeqVec(1) := subDeqPolicyCancelBypassVec(0) 198 199 when (subDeqPolicyValidVec(0)) { 200 assert(Mux1H(io.subDeqSelOH.get(0), entries).bits.status.robIdx === subDeqPolicyEntryVec(0).bits.status.robIdx, "subDeqSelOH(0) is not the same\n") 201 } 202 when (subDeqPolicyValidVec(1)) { 203 assert(Mux1H(io.subDeqSelOH.get(1), entries).bits.status.robIdx === subDeqPolicyEntryVec(1).bits.status.robIdx, "subDeqSelOH(1) is not the same\n") 204 } 205 } 206 else { 207 io.othersEntryOldestSel.zipWithIndex.foreach { case (x, i) => 208 io.deqEntry(i) := Mux(x.valid, othersEntryOldest(i), enqEntryOldest(i)) 209 io.cancelDeqVec(i) := Mux(x.valid, othersEntryOldestCancel(i), enqEntryOldestCancel(i)) 210 } 211 } 212 213 if (params.hasIQWakeUp) { 214 cancelBypassVec.get.zip(srcWakeUpL1ExuOHVec.get).zip(srcTimerVec.get).zip(srcLoadDependencyVec.get).foreach{ case (((cancelBypass: Bool, l1ExuOH: Vec[Vec[Bool]]), srcTimer: Vec[UInt]), srcLoadDependency: Vec[Vec[UInt]]) => 215 val cancelByOg0 = l1ExuOH.zip(srcTimer).map { 216 case(exuOH, srcTimer) => 217 (exuOH.asUInt & io.og0Cancel.asUInt).orR && srcTimer === 1.U 218 }.reduce(_ | _) 219 val cancelByLd = srcLoadDependency.map(x => LoadShouldCancel(Some(x), io.ldCancel)).reduce(_ | _) 220 cancelBypass := cancelByOg0 || cancelByLd 221 } 222 } 223 224 io.valid := validVec.asUInt 225 io.canIssue := canIssueVec.asUInt 226 io.fuType := fuTypeVec 227 io.dataSources := dataSourceVec 228 io.srcWakeUpL1ExuOH.foreach(_ := srcWakeUpL1ExuOHVec.get.map(x => VecInit(x.map(_.asUInt)))) 229 io.srcTimer.foreach(_ := srcTimerVec.get) 230 io.loadDependency.foreach(_ := loadDependencyVec.get) 231 io.isFirstIssue.zipWithIndex.foreach{ case (isFirstIssue, deqIdx) => 232 isFirstIssue := io.deqSelOH(deqIdx).valid && Mux1H(io.deqSelOH(deqIdx).bits, isFirstIssueVec) 233 } 234 io.transSelVec.zip(transSelVec).foreach { case (sink, source) => 235 sink := source.asUInt 236 } 237 io.robIdx.foreach(_ := robIdxVec) 238 io.uopIdx.foreach(_ := uopIdxVec.get) 239 io.rsFeedback := 0.U.asTypeOf(io.rsFeedback) //should be removed 240 io.cancel.foreach(_ := cancelVec.get) //for debug 241 242 def EntriesConnect(in: CommonInBundle, out: CommonOutBundle, entryIdx: Int) = { 243 in.flush := io.flush 244 in.wakeUpFromWB := io.wakeUpFromWB 245 in.wakeUpFromIQ := io.wakeUpFromIQ 246 in.og0Cancel := io.og0Cancel 247 in.og1Cancel := io.og1Cancel 248 in.ldCancel := io.ldCancel 249 in.deqSel := deqSelVec(entryIdx) 250 in.deqPortIdxWrite := deqPortIdxWriteVec(entryIdx) 251 in.issueResp := issueRespVec(entryIdx) 252 if (params.isMemAddrIQ) { 253 in.fromMem.get.stIssuePtr := io.fromMem.get.stIssuePtr 254 in.fromMem.get.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 255 } 256 if (params.isVecMemIQ) { 257 in.fromLsq.get.sqDeqPtr := io.vecMemIn.get.sqDeqPtr 258 in.fromLsq.get.lqDeqPtr := io.vecMemIn.get.lqDeqPtr 259 } 260 validVec(entryIdx) := out.valid 261 canIssueVec(entryIdx) := out.canIssue 262 fuTypeVec(entryIdx) := out.fuType 263 robIdxVec(entryIdx) := out.robIdx 264 dataSourceVec(entryIdx) := out.dataSource 265 isFirstIssueVec(entryIdx) := out.isFirstIssue 266 entries(entryIdx) := out.entry 267 deqPortIdxReadVec(entryIdx) := out.deqPortIdxRead 268 issueTimerVec(entryIdx) := out.issueTimerRead 269 if (params.hasIQWakeUp) { 270 srcWakeUpL1ExuOHVec.get(entryIdx) := out.srcWakeUpL1ExuOH.get 271 srcTimerVec.get(entryIdx) := out.srcTimer.get 272 srcLoadDependencyVec.get(entryIdx) := out.srcLoadDependency.get 273 loadDependencyVec.get(entryIdx) := out.entry.bits.status.mergedLoadDependency.get 274 cancelVec.get(entryIdx) := out.cancel.get 275 } 276 if (params.isVecMemIQ) { 277 uopIdxVec.get(entryIdx) := out.uopIdx.get 278 } 279 } 280} 281 282class EntriesIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle { 283 val flush = Flipped(ValidIO(new Redirect)) 284 //enq 285 val enq = Vec(params.numEnq, Flipped(ValidIO(new EntryBundle))) 286 val og0Resp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 287 val og1Resp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 288 val finalIssueResp = OptionWrapper(params.LdExuCnt > 0, Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))) 289 //deq sel 290 val deqReady = Vec(params.numDeq, Input(Bool())) 291 val deqSelOH = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEntries.W)))) 292 val enqEntryOldestSel = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEnq.W)))) 293 val othersEntryOldestSel= Vec(params.numDeq, Flipped(ValidIO(UInt((params.numEntries - params.numEnq).W)))) 294 val subDeqRequest = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W)))) 295 val subDeqSelOH = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W)))) 296 // wakeup 297 val wakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle) 298 val wakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle) 299 val og0Cancel = Input(ExuOH(backendParams.numExu)) 300 val og1Cancel = Input(ExuOH(backendParams.numExu)) 301 val ldCancel = Vec(backendParams.LdExuCnt, Flipped(new LoadCancelIO)) 302 //trans output 303 val transEntryDeqVec = Vec(params.numEnq, ValidIO(new EntryBundle)) 304 val transSelVec = Output(Vec(params.numEnq, UInt((params.numEntries - params.numEnq).W))) 305 //entries status 306 val valid = Output(UInt(params.numEntries.W)) 307 val canIssue = Output(UInt(params.numEntries.W)) 308 val fuType = Vec(params.numEntries, Output(FuType())) 309 val dataSources = Vec(params.numEntries, Vec(params.numRegSrc, Output(DataSource()))) 310 val srcWakeUpL1ExuOH = OptionWrapper(params.hasIQWakeUp, Vec(params.numEntries, Vec(params.numRegSrc, Output(ExuOH())))) 311 val srcTimer = OptionWrapper(params.hasIQWakeUp, Vec(params.numEntries, Vec(params.numRegSrc, Output(UInt(3.W))))) 312 val loadDependency = OptionWrapper(params.hasIQWakeUp, Vec(params.numEntries, Vec(LoadPipelineWidth, UInt(3.W)))) 313 //deq status 314 val isFirstIssue = Vec(params.numDeq, Output(Bool())) 315 val deqEntry = Vec(params.numDeq, ValidIO(new EntryBundle)) 316 val cancelDeqVec = Vec(params.numDeq, Output(Bool())) 317 // mem only 318 val fromMem = if (params.isMemAddrIQ) Some(new Bundle { 319 val stIssuePtr = Input(new SqPtr) 320 val memWaitUpdateReq = Flipped(new MemWaitUpdateReq) 321 val slowResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 322 val fastResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 323 }) else None 324 val vecMemIn = OptionWrapper(params.isVecMemIQ, new Bundle { 325 val sqDeqPtr = Input(new SqPtr) 326 val lqDeqPtr = Input(new LqPtr) 327 }) 328 329 val robIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, new RobPtr))) 330 val uopIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, UopIdx()))) 331 332 val rsFeedback = Output(Vec(5, Bool())) 333 334 // debug 335 val cancel = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Bool()))) 336 337 def wakeup = wakeUpFromWB ++ wakeUpFromIQ 338} 339