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