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.{MemWaitUpdateReq, SqPtr} 16 17class StatusMemPart(implicit p:Parameters, params: IssueBlockParams) extends Bundle { 18 val waitForSqIdx = new SqPtr // generated by store data valid check 19 val waitForRobIdx = new RobPtr // generated by store set 20 val waitForStd = Bool() 21 val strictWait = Bool() 22 val sqIdx = new SqPtr 23} 24 25class Status(implicit p:Parameters, params: IssueBlockParams) extends XSBundle { 26 val srcState = Vec(params.numRegSrc, SrcState()) 27 28 val psrc = Vec(params.numRegSrc, UInt(params.rdPregIdxWidth.W)) 29 val srcType = Vec(params.numRegSrc, SrcType()) 30 val fuType = FuType() 31 val robIdx = new RobPtr 32 val issued = Bool() // for predict issue 33 val firstIssue = Bool() 34 val blocked = Bool() // for some block reason 35 // read reg or get data from bypass network 36 val dataSources = Vec(params.numRegSrc, DataSource()) 37 // if waked up by iq, set when waked up by iq 38 val srcWakeUpL1ExuOH = OptionWrapper(params.hasIQWakeUp, Vec(params.numRegSrc, ExuOH())) 39 // src timer, used by cancel signal. It increases every cycle after wakeup src inst issued. 40 val srcTimer = OptionWrapper(params.hasIQWakeUp, Vec(params.numRegSrc, UInt(3.W))) 41 val issueTimer = UInt(2.W) 42 val deqPortIdx = UInt(1.W) 43 val srcLoadDependency = OptionWrapper(params.hasIQWakeUp, Vec(params.numRegSrc, Vec(LoadPipelineWidth, UInt(3.W)))) 44 45 46 // mem only 47 val mem = if (params.isMemAddrIQ) Some(new StatusMemPart) else None 48 49 // need pc 50 val pc = if (params.needPc) Some(UInt(VAddrData().dataWidth.W)) else None 51 52 def srcReady: Bool = { 53 VecInit(srcState.map(SrcState.isReady)).asUInt.andR 54 } 55 56 def canIssue: Bool = { 57 srcReady && !issued && !blocked 58 } 59 60 def mergedLoadDependency = { 61 srcLoadDependency.map(_.map(_.toSeq).reduce({ 62 case (l: Vec[UInt], r: Vec[UInt]) => VecInit(l.zip(r).map(x => x._1 | x._2)) 63 }: (Vec[UInt], Vec[UInt]) => Vec[UInt])) 64 } 65} 66 67class EntryDeqRespBundle(implicit p:Parameters, params: IssueBlockParams) extends Bundle { 68 val robIdx = new RobPtr 69 val respType = RSFeedbackType() // update credit if needs replay 70 val dataInvalidSqIdx = new SqPtr 71 val rfWen = Bool() 72 val fuType = FuType() 73} 74 75class EntryBundle(implicit p: Parameters, params: IssueBlockParams) extends XSBundle { 76 val status = new Status() 77 val imm = UInt(XLEN.W) 78 val payload = new DynInst() 79} 80 81class DeqBundle(implicit p:Parameters, params: IssueBlockParams) extends XSBundle { 82 val isFirstIssue = Output(Bool()) 83 val deqSelOH = Flipped(ValidIO(UInt(params.numEntries.W))) 84} 85 86class EntriesIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle { 87 val flush = Flipped(ValidIO(new Redirect)) 88 // status 89 val valid = Output(UInt(params.numEntries.W)) 90 val canIssue = Output(UInt(params.numEntries.W)) 91 val clear = Output(UInt(params.numEntries.W)) 92 val fuType = Output(Vec(params.numEntries, FuType())) 93 val dataSources = Output(Vec(params.numEntries, Vec(params.numRegSrc, DataSource()))) 94 val srcWakeUpL1ExuOH = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Vec(params.numRegSrc, ExuOH())))) 95 val srcTimer = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Vec(params.numRegSrc, UInt(3.W))))) 96 //enq 97 val enq = Vec(params.numEnq, Flipped(ValidIO(new EntryBundle))) 98 // wakeup 99 val wakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle) 100 val wakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle) 101 val og0Cancel = Input(ExuOH(backendParams.numExu)) 102 val og1Cancel = Input(ExuOH(backendParams.numExu)) 103 val ldCancel = Vec(backendParams.LduCnt + backendParams.HyuCnt, Flipped(new LoadCancelIO)) 104 //deq 105 val deq = Vec(params.numDeq, new DeqBundle) 106 val deqResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 107 val og0Resp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 108 val og1Resp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 109 val finalIssueResp = OptionWrapper(params.LdExuCnt > 0, Vec(params.LdExuCnt, Flipped(ValidIO(new EntryDeqRespBundle)))) 110 val memAddrIssueResp = OptionWrapper(params.LdExuCnt > 0, Vec(params.LdExuCnt, Flipped(ValidIO(new EntryDeqRespBundle)))) 111 val transEntryDeqVec = Vec(params.numEnq, ValidIO(new EntryBundle)) 112 val deqEntry = Vec(params.numDeq, ValidIO(new EntryBundle)) 113 val transSelVec = Output(Vec(params.numEnq, UInt((params.numEntries-params.numEnq).W))) 114 115 116 val rsFeedback = Output(Vec(5, Bool())) 117 // mem only 118 val fromMem = if (params.isMemAddrIQ) Some(new Bundle { 119 val stIssuePtr = Input(new SqPtr) 120 val memWaitUpdateReq = Flipped(new MemWaitUpdateReq) 121 val slowResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 122 val fastResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 123 }) else None 124 125 // debug 126 val cancel = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Bool()))) 127 128 def wakeup = wakeUpFromWB ++ wakeUpFromIQ 129} 130 131class Entries(implicit p: Parameters, params: IssueBlockParams) extends XSModule { 132 private val EnqEntryNum = params.numEnq 133 private val OthersEntryNum = params.numEntries - params.numEnq 134 val io = IO(new EntriesIO) 135 136 // only memAddrIQ use it 137 val memEtyResps: MixedVec[ValidIO[EntryDeqRespBundle]] = { 138 if (params.isLdAddrIQ && !params.isStAddrIQ) 139 MixedVecInit(io.deqResp ++ io.og0Resp ++ io.og1Resp ++ io.memAddrIssueResp.get ++ io.finalIssueResp.get) 140 else if (params.isLdAddrIQ && params.isStAddrIQ || params.isHyAddrIQ) 141 MixedVecInit(io.deqResp ++ io.og0Resp ++ io.og1Resp ++ io.memAddrIssueResp.get ++ io.finalIssueResp.get ++ io.fromMem.get.fastResp ++ io.fromMem.get.slowResp) 142 else if (params.isMemAddrIQ) 143 MixedVecInit(io.deqResp ++ io.og0Resp ++ io.og1Resp ++ io.fromMem.get.fastResp ++ io.fromMem.get.slowResp) 144 else MixedVecInit(Seq()) 145 } 146 147 val resps: Vec[Vec[ValidIO[EntryDeqRespBundle]]] = VecInit(io.deqResp, io.og0Resp, io.og1Resp, 0.U.asTypeOf(io.deqResp)) 148 149 //Module 150 val enqEntries = Seq.fill(EnqEntryNum)(Module(EnqEntry(p, params))) 151 val othersEntries = Seq.fill(OthersEntryNum)(Module(OthersEntry(p, params))) 152 val transPolicy = Module(new EnqPolicy) 153 154 //Wire 155 val deqSelVec = Wire(Vec(params.numEntries, Bool())) 156 val transSelVec = Wire(Vec(EnqEntryNum, Vec(OthersEntryNum, Bool()))) 157 val issueRespVec = Wire(Vec(params.numEntries, ValidIO(new EntryDeqRespBundle))) 158 val transEntryDeqVec = Wire(Vec(EnqEntryNum, ValidIO(new EntryBundle))) 159 val transEntryEnqVec = Wire(Vec(OthersEntryNum, ValidIO(new EntryBundle))) 160 val entries = Wire(Vec(params.numEntries, ValidIO(new EntryBundle))) 161 162 val validVec = Wire(Vec(params.numEntries, Bool())) 163 val canIssueVec = Wire(Vec(params.numEntries, Bool())) 164 val clearVec = Wire(Vec(params.numEntries, Bool())) 165 val fuTypeVec = Wire(Vec(params.numEntries, FuType())) 166 val dataSourceVec = Wire(Vec(params.numEntries, Vec(params.numRegSrc, DataSource()))) 167 val srcWakeUpL1ExuOHVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, ExuOH())))) 168 val srcTimerVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, UInt(3.W))))) 169 val isFirstIssueVec = Wire(Vec(params.numEntries, Bool())) 170 val robIdxVec = Wire(Vec(params.numEntries, new RobPtr)) 171 val issueTimerVec = Wire(Vec(params.numEntries, UInt(2.W))) 172 val deqPortIdxWriteVec = Wire(Vec(params.numEntries, UInt(1.W))) 173 val deqPortIdxReadVec = Wire(Vec(params.numEntries, UInt(1.W))) 174 val cancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Bool()))) 175 176 io.transEntryDeqVec := transEntryDeqVec 177 178 //enqEntries 179 enqEntries.zipWithIndex.foreach { case (enqEntry, entryIdx) => 180 enqEntry.io.enq := io.enq(entryIdx) 181 enqEntry.io.flush := io.flush 182 enqEntry.io.wakeUpFromWB := io.wakeUpFromWB 183 enqEntry.io.wakeUpFromIQ := io.wakeUpFromIQ 184 enqEntry.io.og0Cancel := io.og0Cancel 185 enqEntry.io.og1Cancel := io.og1Cancel 186 enqEntry.io.ldCancel := io.ldCancel 187 enqEntry.io.deqSel := deqSelVec(entryIdx) 188 enqEntry.io.deqPortIdxWrite := deqPortIdxWriteVec(entryIdx) 189 enqEntry.io.transSel := transSelVec(entryIdx).asUInt.orR 190 enqEntry.io.issueResp := issueRespVec(entryIdx) 191 validVec(entryIdx) := enqEntry.io.valid 192 canIssueVec(entryIdx) := enqEntry.io.canIssue 193 clearVec(entryIdx) := enqEntry.io.clear 194 fuTypeVec(entryIdx) := enqEntry.io.fuType 195 dataSourceVec(entryIdx) := enqEntry.io.dataSource 196 robIdxVec(entryIdx) := enqEntry.io.robIdx 197 issueTimerVec(entryIdx) := enqEntry.io.issueTimerRead 198 deqPortIdxReadVec(entryIdx) := enqEntry.io.deqPortIdxRead 199 if (params.hasIQWakeUp) { 200 srcWakeUpL1ExuOHVec.get(entryIdx) := enqEntry.io.srcWakeUpL1ExuOH.get 201 srcTimerVec.get(entryIdx) := enqEntry.io.srcTimer.get 202 cancelVec.get(entryIdx) := enqEntry.io.cancel.get 203 } 204 transEntryDeqVec(entryIdx) := enqEntry.io.transEntry 205 isFirstIssueVec(entryIdx) := enqEntry.io.isFirstIssue 206 entries(entryIdx) := enqEntry.io.entry 207 //for mem 208 if (params.isMemAddrIQ) { 209 enqEntry.io.fromMem.get.stIssuePtr := io.fromMem.get.stIssuePtr 210 enqEntry.io.fromMem.get.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 211 } 212 213 } 214 //othersEntries 215 othersEntries.zipWithIndex.foreach { case (othersEntry, entryIdx) => 216 othersEntry.io.enq := transEntryEnqVec(entryIdx) 217 othersEntry.io.flush := io.flush 218 othersEntry.io.wakeUpFromWB := io.wakeUpFromWB 219 othersEntry.io.wakeUpFromIQ := io.wakeUpFromIQ 220 othersEntry.io.og0Cancel := io.og0Cancel 221 othersEntry.io.og1Cancel := io.og1Cancel 222 othersEntry.io.ldCancel := io.ldCancel 223 othersEntry.io.deqSel := deqSelVec(entryIdx + EnqEntryNum) 224 othersEntry.io.deqPortIdxWrite := deqPortIdxWriteVec(entryIdx + EnqEntryNum) 225 othersEntry.io.transSel := transSelVec.map(x => x(entryIdx)).reduce(_ | _) 226 othersEntry.io.issueResp := issueRespVec(entryIdx + EnqEntryNum) 227 validVec(entryIdx + EnqEntryNum) := othersEntry.io.valid 228 canIssueVec(entryIdx + EnqEntryNum) := othersEntry.io.canIssue 229 clearVec(entryIdx + EnqEntryNum) := othersEntry.io.clear 230 fuTypeVec(entryIdx + EnqEntryNum) := othersEntry.io.fuType 231 dataSourceVec(entryIdx + EnqEntryNum) := othersEntry.io.dataSource 232 robIdxVec(entryIdx + EnqEntryNum) := othersEntry.io.robIdx 233 issueTimerVec(entryIdx + EnqEntryNum) := othersEntry.io.issueTimerRead 234 deqPortIdxReadVec(entryIdx + EnqEntryNum) := othersEntry.io.deqPortIdxRead 235 if (params.hasIQWakeUp) { 236 srcWakeUpL1ExuOHVec.get(entryIdx + EnqEntryNum) := othersEntry.io.srcWakeUpL1ExuOH.get 237 srcTimerVec.get(entryIdx + EnqEntryNum) := othersEntry.io.srcTimer.get 238 cancelVec.get(entryIdx + EnqEntryNum) := othersEntry.io.cancel.get 239 } 240 isFirstIssueVec(entryIdx + EnqEntryNum) := othersEntry.io.isFirstIssue 241 entries(entryIdx + EnqEntryNum) := othersEntry.io.entry 242 //for mem 243 if (params.isMemAddrIQ) { 244 othersEntry.io.fromMem.get.stIssuePtr := io.fromMem.get.stIssuePtr 245 othersEntry.io.fromMem.get.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 246 } 247 248 } 249 250 251 deqSelVec.zip(deqPortIdxWriteVec).zipWithIndex.foreach { case ((deqSel, deqPortIdxWrite), i) => 252 val deqVec = io.deq.map(x => x.deqSelOH.valid && x.deqSelOH.bits(i)) 253 deqPortIdxWrite := OHToUInt(deqVec) 254 deqSel := deqVec.reduce(_ | _) 255 } 256 257 258 //transPolicy 259 transPolicy.io.valid := VecInit(validVec.slice(EnqEntryNum, params.numEntries)).asUInt 260 transSelVec.zip(transPolicy.io.enqSelOHVec).foreach { case (selBools, selOH) => 261 selBools.zipWithIndex.foreach { case (selBool, i) => 262 selBool := transPolicy.io.enqSelOHVec.map(_.valid).reduce(_ & _) && selOH.bits(i) 263 } 264 } 265 266 //transEntryEnq 267 transEntryEnqVec.zipWithIndex.foreach { case (transEntryEnq, othersIdx) => 268 val transEnqHit = transSelVec.map(x => x(othersIdx)) 269 transEntryEnq := Mux1H(transEnqHit, transEntryDeqVec) 270 } 271 dontTouch(transEntryEnqVec) 272 273 //issueRespVec 274 if(params.isMemAddrIQ){ 275 issueRespVec.zip(robIdxVec).foreach { case (issueResp, robIdx) => 276 val hitRespsVec = VecInit(memEtyResps.map(x => x.valid && (x.bits.robIdx === robIdx)).toSeq) 277 issueResp.valid := hitRespsVec.reduce(_ | _) 278 issueResp.bits := Mux1H(hitRespsVec, memEtyResps.map(_.bits).toSeq) 279 } 280 } 281 else { 282 issueRespVec.zip(issueTimerVec).zip(deqPortIdxReadVec).foreach { case ((issueResp, issueTimer), deqPortIdx) => 283 val Resp = resps(issueTimer)(deqPortIdx) 284 issueResp := Resp 285 } 286 } 287 288 io.valid := validVec.asUInt 289 io.canIssue := canIssueVec.asUInt 290 io.clear := clearVec.asUInt 291 io.fuType := fuTypeVec 292 io.dataSources := dataSourceVec 293 io.srcWakeUpL1ExuOH.foreach(_ := srcWakeUpL1ExuOHVec.get) 294 io.srcTimer.foreach(_ := srcTimerVec.get) 295 io.cancel.foreach(_ := cancelVec.get) 296 io.rsFeedback := 0.U.asTypeOf(io.rsFeedback) //todo 297 io.deq.foreach{ x => 298 x.isFirstIssue := Mux(x.deqSelOH.valid, Mux1H(x.deqSelOH.bits, isFirstIssueVec), false.B) 299 } 300 dontTouch(io.deq) 301 io.deqEntry.zip(io.deq.map(_.deqSelOH)).foreach{ case (deqEntry, deqSelOH) => 302 deqEntry.valid := deqSelOH.valid && entries(OHToUInt(deqSelOH.bits)).valid 303 deqEntry.bits := entries(OHToUInt(deqSelOH.bits)).bits 304 } 305 io.transSelVec.zip(transSelVec).foreach { case (sink, source) => 306 sink := source.asUInt 307 } 308} 309