1package xiangshan.backend.issue 2 3import chipsalliance.rocketchip.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, ExuVec())) 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 val target = if(params.needPc) Some(UInt(VAddrData().dataWidth.W)) else None 52 53 def srcReady: Bool = { 54 VecInit(srcState.map(SrcState.isReady)).asUInt.andR 55 } 56 57 def canIssue: Bool = { 58 srcReady && !issued && !blocked 59 } 60 61 def mergedLoadDependency = srcLoadDependency.map(_.map(_.toSeq).reduce(_ zip _ map(x => x._1 | x._2))) 62} 63 64class EntryDeqRespBundle(implicit p:Parameters, params: IssueBlockParams) extends Bundle { 65 val robIdx = new RobPtr 66 val respType = RSFeedbackType() // update credit if needs replay 67 val dataInvalidSqIdx = new SqPtr 68 val rfWen = Bool() 69 val fuType = FuType() 70} 71 72class EntryBundle(implicit p: Parameters, params: IssueBlockParams) extends XSBundle { 73 val status = new Status() 74 val imm = UInt(XLEN.W) 75 val payload = new DynInst() 76} 77 78class DeqBundle(implicit p:Parameters, params: IssueBlockParams) extends XSBundle { 79 val isFirstIssue = Output(Bool()) 80 val deqSelOH = Flipped(ValidIO(UInt(params.numEntries.W))) 81} 82 83class EntriesIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle { 84 val flush = Flipped(ValidIO(new Redirect)) 85 // status 86 val valid = Output(UInt(params.numEntries.W)) 87 val canIssue = Output(UInt(params.numEntries.W)) 88 val clear = Output(UInt(params.numEntries.W)) 89 val fuType = Output(Vec(params.numEntries, FuType())) 90 val dataSources = Output(Vec(params.numEntries, Vec(params.numRegSrc, DataSource()))) 91 val srcWakeUpL1ExuOH = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Vec(params.numRegSrc, ExuVec())))) 92 val srcTimer = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Vec(params.numRegSrc, UInt(3.W))))) 93 //enq 94 val enq = Vec(params.numEnq, Flipped(ValidIO(new EntryBundle))) 95 // wakeup 96 val wakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle) 97 val wakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle) 98 val og0Cancel = Input(ExuVec(backendParams.numExu)) 99 val og1Cancel = Input(ExuVec(backendParams.numExu)) 100 val ldCancel = Vec(backendParams.LduCnt, Flipped(new LoadCancelIO)) 101 //deq 102 val deq = Vec(params.numDeq, new DeqBundle) 103 val deqResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 104 val og0Resp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 105 val og1Resp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 106 val finalIssueResp = OptionWrapper(params.LduCnt > 0, Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))) 107 val transEntryDeqVec = Vec(params.numEnq, ValidIO(new EntryBundle)) 108 val deqEntry = Vec(params.numDeq, ValidIO(new EntryBundle)) 109 val transSelVec = Output(Vec(params.numEnq, UInt((params.numEntries-params.numEnq).W))) 110 111 112 val rsFeedback = Output(Vec(5, Bool())) 113 // mem only 114 val fromMem = if (params.isMemAddrIQ) Some(new Bundle { 115 val stIssuePtr = Input(new SqPtr) 116 val memWaitUpdateReq = Flipped(new MemWaitUpdateReq) 117 val slowResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 118 val fastResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))) 119 }) else None 120 121 def wakeup = wakeUpFromWB ++ wakeUpFromIQ 122} 123 124class Entries(implicit p: Parameters, params: IssueBlockParams) extends XSModule { 125 private val EnqEntryNum = params.numEnq 126 private val OthersEntryNum = params.numEntries - params.numEnq 127 val io = IO(new EntriesIO) 128 129 val resps: Vec[Vec[ValidIO[EntryDeqRespBundle]]] = if(params.isLdAddrIQ) VecInit(io.deqResp, io.og0Resp, io.og1Resp, io.finalIssueResp.get, io.fromMem.get.fastResp, io.fromMem.get.slowResp) 130 else if(params.isMemAddrIQ) VecInit(io.deqResp, io.og0Resp, io.og1Resp, io.fromMem.get.fastResp, io.fromMem.get.slowResp) 131 else VecInit(io.deqResp, io.og0Resp, io.og1Resp, 0.U.asTypeOf(io.deqResp)) 132 133 //Module 134 val enqEntries = Seq.fill(EnqEntryNum)(Module(EnqEntry(p, params))) 135 val othersEntries = Seq.fill(OthersEntryNum)(Module(OthersEntry(p, params))) 136 val transPolicy = Module(new EnqPolicy) 137 138 //Wire 139 val deqSelVec = Wire(Vec(params.numEntries, Bool())) 140 val transSelVec = Wire(Vec(EnqEntryNum, Vec(OthersEntryNum, Bool()))) 141 val issueRespVec = Wire(Vec(params.numEntries, ValidIO(new EntryDeqRespBundle))) 142 val transEntryDeqVec = Wire(Vec(EnqEntryNum, ValidIO(new EntryBundle))) 143 val transEntryEnqVec = Wire(Vec(OthersEntryNum, ValidIO(new EntryBundle))) 144 val entries = Wire(Vec(params.numEntries, ValidIO(new EntryBundle))) 145 146 val validVec = Wire(Vec(params.numEntries, Bool())) 147 val canIssueVec = Wire(Vec(params.numEntries, Bool())) 148 val clearVec = Wire(Vec(params.numEntries, Bool())) 149 val fuTypeVec = Wire(Vec(params.numEntries, FuType())) 150 val dataSourceVec = Wire(Vec(params.numEntries, Vec(params.numRegSrc, DataSource()))) 151 val srcWakeUpL1ExuOHVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, ExuVec())))) 152 val srcTimerVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, UInt(3.W))))) 153 val isFirstIssueVec = Wire(Vec(params.numEntries, Bool())) 154 val robIdxVec = Wire(Vec(params.numEntries, new RobPtr)) 155 val issueTimerVec = Wire(Vec(params.numEntries, UInt(2.W))) 156 val deqPortIdxWriteVec = Wire(Vec(params.numEntries, UInt(1.W))) 157 val deqPortIdxReadVec = Wire(Vec(params.numEntries, UInt(1.W))) 158 159 io.transEntryDeqVec := transEntryDeqVec 160 161 //enqEntries 162 enqEntries.zipWithIndex.foreach { case (enqEntry, entryIdx) => 163 enqEntry.io.enq := io.enq(entryIdx) 164 enqEntry.io.flush := io.flush 165 enqEntry.io.wakeUpFromWB := io.wakeUpFromWB 166 enqEntry.io.wakeUpFromIQ := io.wakeUpFromIQ 167 enqEntry.io.og0Cancel := io.og0Cancel 168 enqEntry.io.og1Cancel := io.og1Cancel 169 enqEntry.io.ldCancel := io.ldCancel 170 enqEntry.io.deqSel := deqSelVec(entryIdx) 171 enqEntry.io.deqPortIdxWrite := deqPortIdxWriteVec(entryIdx) 172 enqEntry.io.transSel := transSelVec(entryIdx).asUInt.orR 173 enqEntry.io.issueResp := issueRespVec(entryIdx) 174 validVec(entryIdx) := enqEntry.io.valid 175 canIssueVec(entryIdx) := enqEntry.io.canIssue 176 clearVec(entryIdx) := enqEntry.io.clear 177 fuTypeVec(entryIdx) := enqEntry.io.fuType 178 dataSourceVec(entryIdx) := enqEntry.io.dataSource 179 robIdxVec(entryIdx) := enqEntry.io.robIdx 180 issueTimerVec(entryIdx) := enqEntry.io.issueTimerRead 181 deqPortIdxReadVec(entryIdx) := enqEntry.io.deqPortIdxRead 182 if(params.hasIQWakeUp){ 183 srcWakeUpL1ExuOHVec.get(entryIdx) := enqEntry.io.srcWakeUpL1ExuOH.get 184 srcTimerVec.get(entryIdx) := enqEntry.io.srcTimer.get 185 } 186 transEntryDeqVec(entryIdx) := enqEntry.io.transEntry 187 isFirstIssueVec(entryIdx) := enqEntry.io.isFirstIssue 188 entries(entryIdx) := enqEntry.io.entry 189 //for mem 190 if(params.isMemAddrIQ) { 191 enqEntry.io.fromMem.get.stIssuePtr := io.fromMem.get.stIssuePtr 192 enqEntry.io.fromMem.get.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 193 } 194 195 } 196 //othersEntries 197 othersEntries.zipWithIndex.foreach { case (othersEntry, entryIdx) => 198 othersEntry.io.enq := transEntryEnqVec(entryIdx) 199 othersEntry.io.flush := io.flush 200 othersEntry.io.wakeUpFromWB := io.wakeUpFromWB 201 othersEntry.io.wakeUpFromIQ := io.wakeUpFromIQ 202 othersEntry.io.og0Cancel := io.og0Cancel 203 othersEntry.io.og1Cancel := io.og1Cancel 204 othersEntry.io.ldCancel := io.ldCancel 205 othersEntry.io.deqSel := deqSelVec(entryIdx + EnqEntryNum) 206 othersEntry.io.deqPortIdxWrite := deqPortIdxWriteVec(entryIdx + EnqEntryNum) 207 othersEntry.io.transSel := transSelVec.map(x => x(entryIdx)).reduce(_ | _) 208 othersEntry.io.issueResp := issueRespVec(entryIdx + EnqEntryNum) 209 validVec(entryIdx + EnqEntryNum) := othersEntry.io.valid 210 canIssueVec(entryIdx + EnqEntryNum) := othersEntry.io.canIssue 211 clearVec(entryIdx + EnqEntryNum) := othersEntry.io.clear 212 fuTypeVec(entryIdx + EnqEntryNum) := othersEntry.io.fuType 213 dataSourceVec(entryIdx + EnqEntryNum) := othersEntry.io.dataSource 214 robIdxVec(entryIdx + EnqEntryNum) := othersEntry.io.robIdx 215 issueTimerVec(entryIdx + EnqEntryNum) := othersEntry.io.issueTimerRead 216 deqPortIdxReadVec(entryIdx + EnqEntryNum) := othersEntry.io.deqPortIdxRead 217 if (params.hasIQWakeUp) { 218 srcWakeUpL1ExuOHVec.get(entryIdx + EnqEntryNum) := othersEntry.io.srcWakeUpL1ExuOH.get 219 srcTimerVec.get(entryIdx + EnqEntryNum) := othersEntry.io.srcTimer.get 220 } 221 isFirstIssueVec(entryIdx + EnqEntryNum) := othersEntry.io.isFirstIssue 222 entries(entryIdx + EnqEntryNum) := othersEntry.io.entry 223 //for mem 224 if (params.isMemAddrIQ) { 225 othersEntry.io.fromMem.get.stIssuePtr := io.fromMem.get.stIssuePtr 226 othersEntry.io.fromMem.get.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 227 } 228 229 } 230 231 232 deqSelVec.zip(deqPortIdxWriteVec).zipWithIndex.foreach { case ((deqSel, deqPortIdxWrite), i) => 233 val deqVec = io.deq.map(x => x.deqSelOH.valid && x.deqSelOH.bits(i)) 234 deqPortIdxWrite := OHToUInt(deqVec) 235 deqSel := deqVec.reduce(_ | _) 236 } 237 238 239 //transPolicy 240 transPolicy.io.valid := VecInit(validVec.slice(EnqEntryNum, params.numEntries)).asUInt 241 transSelVec.zip(transPolicy.io.enqSelOHVec).foreach { case (selBools, selOH) => 242 selBools.zipWithIndex.foreach { case (selBool, i) => 243 selBool := transPolicy.io.enqSelOHVec.map(_.valid).reduce(_ & _) && selOH.bits(i) 244 } 245 } 246 247 //transEntryEnq 248 transEntryEnqVec.zipWithIndex.foreach { case (transEntryEnq, othersIdx) => 249 val transEnqHit = transSelVec.map(x => x(othersIdx)) 250 transEntryEnq := Mux1H(transEnqHit, transEntryDeqVec) 251 } 252 dontTouch(transEntryEnqVec) 253 254 //issueRespVec 255 if(params.isMemAddrIQ){ 256 issueRespVec.zip(robIdxVec).foreach { case (issueResp, robIdx) => 257 val hitRespsVec = VecInit(resps.flatten.map(x => x.valid && (x.bits.robIdx === robIdx))) 258 issueResp.valid := hitRespsVec.reduce(_ | _) 259 issueResp.bits := Mux1H(hitRespsVec, resps.flatten.map(_.bits)) 260 } 261 } 262 else { 263 issueRespVec.zip(issueTimerVec).zip(deqPortIdxReadVec).foreach { case ((issueResp, issueTimer), deqPortIdx) => 264 val Resp = resps(issueTimer)(deqPortIdx) 265 issueResp := Resp 266 } 267 } 268 269 io.valid := validVec.asUInt 270 io.canIssue := canIssueVec.asUInt 271 io.clear := clearVec.asUInt 272 io.fuType := fuTypeVec 273 io.dataSources := dataSourceVec 274 io.srcWakeUpL1ExuOH.foreach(_ := srcWakeUpL1ExuOHVec.get) 275 io.srcTimer.foreach(_ := srcTimerVec.get) 276 io.rsFeedback := 0.U.asTypeOf(io.rsFeedback) //todo 277 io.deq.foreach{ x => 278 x.isFirstIssue := Mux(x.deqSelOH.valid, Mux1H(x.deqSelOH.bits, isFirstIssueVec), false.B) 279 } 280 dontTouch(io.deq) 281 io.deqEntry.zip(io.deq.map(_.deqSelOH)).foreach{ case (deqEntry, deqSelOH) => 282 deqEntry.valid := deqSelOH.valid && entries(OHToUInt(deqSelOH.bits)).valid 283 deqEntry.bits := entries(OHToUInt(deqSelOH.bits)).bits 284 } 285 io.transSelVec.zip(transSelVec).foreach { case (sink, source) => 286 sink := source.asUInt 287 } 288} 289