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