1package xiangshan.backend.issue 2 3import org.chipsalliance.cde.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 7import utils.{HasPerfEvents, OptionWrapper} 8import xiangshan._ 9import xiangshan.backend.Bundles._ 10import xiangshan.backend.datapath.DataConfig._ 11import xiangshan.backend.datapath.WbConfig._ 12import xiangshan.backend.fu.FuType 13import xiangshan.backend.regfile.RfWritePortWithConfig 14import xiangshan.backend.rename.BusyTable 15import xiangshan.mem.{LsqEnqCtrl, LsqEnqIO, MemWaitUpdateReq, SqPtr, LqPtr} 16import xiangshan.backend.datapath.WbConfig.V0WB 17import xiangshan.backend.regfile.VlPregParams 18 19sealed trait SchedulerType 20 21case class IntScheduler() extends SchedulerType 22case class FpScheduler() extends SchedulerType 23case class MemScheduler() extends SchedulerType 24case class VfScheduler() extends SchedulerType 25case class NoScheduler() extends SchedulerType 26 27class Scheduler(val params: SchdBlockParams)(implicit p: Parameters) extends LazyModule with HasXSParameter { 28 override def shouldBeInlined: Boolean = false 29 30 val numIntStateWrite = backendParams.numPregWb(IntData()) 31 val numFpStateWrite = backendParams.numPregWb(FpData()) 32 val numVfStateWrite = backendParams.numPregWb(VecData()) 33 val numV0StateWrite = backendParams.numPregWb(V0Data()) 34 val numVlStateWrite = backendParams.numPregWb(VlData()) 35 36 val dispatch2Iq = LazyModule(new Dispatch2Iq(params)) 37 val issueQueue = params.issueBlockParams.map(x => LazyModule(new IssueQueue(x).suggestName(x.getIQName))) 38 39 lazy val module: SchedulerImpBase = params.schdType match { 40 case IntScheduler() => new SchedulerArithImp(this)(params, p) 41 case FpScheduler() => new SchedulerArithImp(this)(params, p) 42 case MemScheduler() => new SchedulerMemImp(this)(params, p) 43 case VfScheduler() => new SchedulerArithImp(this)(params, p) 44 case _ => null 45 } 46} 47 48class SchedulerIO()(implicit params: SchdBlockParams, p: Parameters) extends XSBundle { 49 // params alias 50 private val LoadQueueSize = VirtualLoadQueueSize 51 52 val fromTop = new Bundle { 53 val hartId = Input(UInt(8.W)) 54 } 55 val fromWbFuBusyTable = new Bundle{ 56 val fuBusyTableRead = MixedVec(params.issueBlockParams.map(x => Input(x.genWbFuBusyTableReadBundle))) 57 } 58 val wbFuBusyTable = MixedVec(params.issueBlockParams.map(x => Output(x.genWbFuBusyTableWriteBundle))) 59 val intIQValidNumVec = Output(MixedVec(backendParams.genIntIQValidNumBundle)) 60 val fpIQValidNumVec = Output(MixedVec(backendParams.genFpIQValidNumBundle)) 61 62 val fromCtrlBlock = new Bundle { 63 val flush = Flipped(ValidIO(new Redirect)) 64 } 65 val fromDispatch = new Bundle { 66 val allocPregs = Vec(RenameWidth, Input(new ResetPregStateReq)) 67 val uops = Vec(params.numUopIn, Flipped(DecoupledIO(new DynInst))) 68 } 69 val intWriteBack = MixedVec(Vec(backendParams.numPregWb(IntData()), 70 new RfWritePortWithConfig(backendParams.intPregParams.dataCfg, backendParams.intPregParams.addrWidth))) 71 val fpWriteBack = MixedVec(Vec(backendParams.numPregWb(FpData()), 72 new RfWritePortWithConfig(backendParams.fpPregParams.dataCfg, backendParams.fpPregParams.addrWidth))) 73 val vfWriteBack = MixedVec(Vec(backendParams.numPregWb(VecData()), 74 new RfWritePortWithConfig(backendParams.vfPregParams.dataCfg, backendParams.vfPregParams.addrWidth))) 75 val v0WriteBack = MixedVec(Vec(backendParams.numPregWb(V0Data()), 76 new RfWritePortWithConfig(backendParams.v0PregParams.dataCfg, backendParams.v0PregParams.addrWidth))) 77 val vlWriteBack = MixedVec(Vec(backendParams.numPregWb(VlData()), 78 new RfWritePortWithConfig(backendParams.vlPregParams.dataCfg, backendParams.vlPregParams.addrWidth))) 79 val toDataPathAfterDelay: MixedVec[MixedVec[DecoupledIO[IssueQueueIssueBundle]]] = MixedVec(params.issueBlockParams.map(_.genIssueDecoupledBundle)) 80 81 val vlWriteBackInfo = new Bundle { 82 val vlIsZero = Input(Bool()) 83 val vlIsVlmax = Input(Bool()) 84 } 85 86 val fromSchedulers = new Bundle { 87 val wakeupVec: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpInValidBundle) 88 } 89 90 val toSchedulers = new Bundle { 91 val wakeupVec: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = params.genIQWakeUpOutValidBundle 92 } 93 94 val fromDataPath = new Bundle { 95 val resp: MixedVec[MixedVec[OGRespBundle]] = MixedVec(params.issueBlockParams.map(x => Flipped(x.genOGRespBundle))) 96 val og0Cancel = Input(ExuVec()) 97 // Todo: remove this after no cancel signal from og1 98 val og1Cancel = Input(ExuVec()) 99 // just be compatible to old code 100 def apply(i: Int)(j: Int) = resp(i)(j) 101 } 102 103 val loadFinalIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.LdExuCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x))))))) 104 val memAddrIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.LdExuCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x))))))) 105 val vecLoadIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.VlduCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x))))))) 106 107 val ldCancel = Vec(backendParams.LduCnt + backendParams.HyuCnt, Flipped(new LoadCancelIO)) 108 109 val memIO = if (params.isMemSchd) Some(new Bundle { 110 val lsqEnqIO = Flipped(new LsqEnqIO) 111 }) else None 112 val fromMem = if (params.isMemSchd) Some(new Bundle { 113 val ldaFeedback = Flipped(Vec(params.LduCnt, new MemRSFeedbackIO)) 114 val staFeedback = Flipped(Vec(params.StaCnt, new MemRSFeedbackIO)) 115 val hyuFeedback = Flipped(Vec(params.HyuCnt, new MemRSFeedbackIO)) 116 val vstuFeedback = Flipped(Vec(params.VstuCnt, new MemRSFeedbackIO(isVector = true))) 117 val vlduFeedback = Flipped(Vec(params.VlduCnt, new MemRSFeedbackIO(isVector = true))) 118 val stIssuePtr = Input(new SqPtr()) 119 val lcommit = Input(UInt(log2Up(CommitWidth + 1).W)) 120 val scommit = Input(UInt(log2Ceil(EnsbufferWidth + 1).W)) // connected to `memBlock.io.sqDeq` instead of ROB 121 val wakeup = Vec(params.LdExuCnt, Flipped(Valid(new DynInst))) 122 val lqDeqPtr = Input(new LqPtr) 123 val sqDeqPtr = Input(new SqPtr) 124 // from lsq 125 val lqCancelCnt = Input(UInt(log2Up(LoadQueueSize + 1).W)) 126 val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W)) 127 val memWaitUpdateReq = Flipped(new MemWaitUpdateReq) 128 }) else None 129 val toMem = if (params.isMemSchd) Some(new Bundle { 130 val loadFastMatch = Output(Vec(params.LduCnt, new IssueQueueLoadBundle)) 131 }) else None 132 val fromOg2 = if(params.isVfSchd) Some(MixedVec(params.issueBlockParams.map(x => Flipped(x.genOG2RespBundle)))) else None 133} 134 135abstract class SchedulerImpBase(wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 136 extends LazyModuleImp(wrapper) 137 with HasXSParameter 138{ 139 val io = IO(new SchedulerIO()) 140 141 // alias 142 private val iqWakeUpInMap: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] = 143 io.fromSchedulers.wakeupVec.map(x => (x.bits.exuIdx, x)).toMap 144 private val schdType = params.schdType 145 146 // Modules 147 val dispatch2Iq: Dispatch2IqImp = wrapper.dispatch2Iq.module 148 val issueQueues: Seq[IssueQueueImp] = wrapper.issueQueue.map(_.module) 149 io.intIQValidNumVec := 0.U.asTypeOf(io.intIQValidNumVec) 150 io.fpIQValidNumVec := 0.U.asTypeOf(io.fpIQValidNumVec) 151 if (params.isIntSchd) { 152 dispatch2Iq.io.intIQValidNumVec.get := io.intIQValidNumVec 153 io.intIQValidNumVec := MixedVecInit(issueQueues.map(_.io.validCntDeqVec)) 154 } 155 else if (params.isFpSchd) { 156 dispatch2Iq.io.fpIQValidNumVec.get := io.fpIQValidNumVec 157 io.fpIQValidNumVec := MixedVecInit(issueQueues.map(_.io.validCntDeqVec)) 158 } 159 160 // valid count 161 dispatch2Iq.io.iqValidCnt := issueQueues.filter(_.params.StdCnt == 0).map(_.io.status.validCnt) 162 163 // BusyTable Modules 164 val intBusyTable = schdType match { 165 case IntScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numIntStateRead, wrapper.numIntStateWrite, IntPhyRegs, IntWB()))) 166 case _ => None 167 } 168 val fpBusyTable = schdType match { 169 case FpScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numFpStateRead, wrapper.numFpStateWrite, FpPhyRegs, FpWB()))) 170 case _ => None 171 } 172 val vfBusyTable = schdType match { 173 case VfScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numVfStateRead, wrapper.numVfStateWrite, VfPhyRegs, VfWB()))) 174 case _ => None 175 } 176 val v0BusyTable = schdType match { 177 case VfScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numV0StateRead, wrapper.numV0StateWrite, V0PhyRegs, V0WB()))) 178 case _ => None 179 } 180 val vlBusyTable = schdType match { 181 case VfScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numVlStateRead, wrapper.numVlStateWrite, VlPhyRegs, VlWB()))) 182 case _ => None 183 } 184 185 dispatch2Iq.io match { case dp2iq => 186 dp2iq.redirect <> io.fromCtrlBlock.flush 187 dp2iq.in <> io.fromDispatch.uops 188 dp2iq.readIntState.foreach(_ <> intBusyTable.get.io.read) 189 dp2iq.readFpState.foreach(_ <> fpBusyTable.get.io.read) 190 dp2iq.readVfState.foreach(_ <> vfBusyTable.get.io.read) 191 dp2iq.readV0State.foreach(_ <> v0BusyTable.get.io.read) 192 dp2iq.readVlState.foreach(_ <> vlBusyTable.get.io.read) 193 } 194 195 intBusyTable match { 196 case Some(bt) => 197 bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) => 198 btAllocPregs.valid := dpAllocPregs.isInt 199 btAllocPregs.bits := dpAllocPregs.preg 200 } 201 bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) => 202 wb.valid := io.intWriteBack(i).wen && io.intWriteBack(i).intWen 203 wb.bits := io.intWriteBack(i).addr 204 } 205 bt.io.wakeUp := io.fromSchedulers.wakeupVec 206 bt.io.og0Cancel := io.fromDataPath.og0Cancel 207 bt.io.ldCancel := io.ldCancel 208 case None => 209 } 210 211 fpBusyTable match { 212 case Some(bt) => 213 bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) => 214 btAllocPregs.valid := dpAllocPregs.isFp 215 btAllocPregs.bits := dpAllocPregs.preg 216 } 217 bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) => 218 wb.valid := io.fpWriteBack(i).wen && io.fpWriteBack(i).fpWen 219 wb.bits := io.fpWriteBack(i).addr 220 } 221 bt.io.wakeUp := io.fromSchedulers.wakeupVec 222 bt.io.og0Cancel := io.fromDataPath.og0Cancel 223 bt.io.ldCancel := io.ldCancel 224 case None => 225 } 226 227 vfBusyTable match { 228 case Some(bt) => 229 bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) => 230 btAllocPregs.valid := dpAllocPregs.isVec 231 btAllocPregs.bits := dpAllocPregs.preg 232 } 233 bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) => 234 wb.valid := io.vfWriteBack(i).wen && io.vfWriteBack(i).vecWen 235 wb.bits := io.vfWriteBack(i).addr 236 } 237 bt.io.wakeUp := io.fromSchedulers.wakeupVec 238 bt.io.og0Cancel := io.fromDataPath.og0Cancel 239 bt.io.ldCancel := io.ldCancel 240 case None => 241 } 242 243 v0BusyTable match { 244 case Some(bt) => 245 bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) => 246 btAllocPregs.valid := dpAllocPregs.isV0 247 btAllocPregs.bits := dpAllocPregs.preg 248 } 249 bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) => 250 wb.valid := io.v0WriteBack(i).wen && io.v0WriteBack(i).v0Wen 251 wb.bits := io.v0WriteBack(i).addr 252 } 253 bt.io.wakeUp := io.fromSchedulers.wakeupVec 254 bt.io.og0Cancel := io.fromDataPath.og0Cancel 255 bt.io.ldCancel := io.ldCancel 256 case None => 257 } 258 259 vlBusyTable match { 260 case Some(bt) => 261 bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) => 262 btAllocPregs.valid := dpAllocPregs.isVl 263 btAllocPregs.bits := dpAllocPregs.preg 264 } 265 bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) => 266 wb.valid := io.vlWriteBack(i).wen && io.vlWriteBack(i).vlWen 267 wb.bits := io.vlWriteBack(i).addr 268 } 269 bt.io.wakeUp := io.fromSchedulers.wakeupVec 270 bt.io.og0Cancel := io.fromDataPath.og0Cancel 271 bt.io.ldCancel := io.ldCancel 272 case None => 273 } 274 275 val wakeupFromIntWBVec = Wire(params.genIntWBWakeUpSinkValidBundle) 276 val wakeupFromFpWBVec = Wire(params.genFpWBWakeUpSinkValidBundle) 277 val wakeupFromVfWBVec = Wire(params.genVfWBWakeUpSinkValidBundle) 278 val wakeupFromV0WBVec = Wire(params.genV0WBWakeUpSinkValidBundle) 279 val wakeupFromVlWBVec = Wire(params.genVlWBWakeUpSinkValidBundle) 280 281 wakeupFromIntWBVec.zip(io.intWriteBack).foreach { case (sink, source) => 282 sink.valid := source.wen 283 sink.bits.rfWen := source.intWen 284 sink.bits.fpWen := source.fpWen 285 sink.bits.vecWen := source.vecWen 286 sink.bits.v0Wen := source.v0Wen 287 sink.bits.vlWen := source.vlWen 288 sink.bits.pdest := source.addr 289 } 290 291 wakeupFromFpWBVec.zip(io.fpWriteBack).foreach { case (sink, source) => 292 sink.valid := source.wen 293 sink.bits.rfWen := source.intWen 294 sink.bits.fpWen := source.fpWen 295 sink.bits.vecWen := source.vecWen 296 sink.bits.v0Wen := source.v0Wen 297 sink.bits.vlWen := source.vlWen 298 sink.bits.pdest := source.addr 299 } 300 301 wakeupFromVfWBVec.zip(io.vfWriteBack).foreach { case (sink, source) => 302 sink.valid := source.wen 303 sink.bits.rfWen := source.intWen 304 sink.bits.fpWen := source.fpWen 305 sink.bits.vecWen := source.vecWen 306 sink.bits.v0Wen := source.v0Wen 307 sink.bits.vlWen := source.vlWen 308 sink.bits.pdest := source.addr 309 } 310 311 wakeupFromV0WBVec.zip(io.v0WriteBack).foreach { case (sink, source) => 312 sink.valid := source.wen 313 sink.bits.rfWen := source.intWen 314 sink.bits.fpWen := source.fpWen 315 sink.bits.vecWen := source.vecWen 316 sink.bits.v0Wen := source.v0Wen 317 sink.bits.vlWen := source.vlWen 318 sink.bits.pdest := source.addr 319 } 320 321 wakeupFromVlWBVec.zip(io.vlWriteBack).foreach { case (sink, source) => 322 sink.valid := source.wen 323 sink.bits.rfWen := source.intWen 324 sink.bits.fpWen := source.fpWen 325 sink.bits.vecWen := source.vecWen 326 sink.bits.v0Wen := source.v0Wen 327 sink.bits.vlWen := source.vlWen 328 sink.bits.pdest := source.addr 329 } 330 331 // Connect bundles having the same wakeup source 332 issueQueues.zipWithIndex.foreach { case(iq, i) => 333 iq.io.wakeupFromIQ.foreach { wakeUp => 334 val wakeUpIn = iqWakeUpInMap(wakeUp.bits.exuIdx) 335 val exuIdx = wakeUp.bits.exuIdx 336 println(s"[Backend] Connect wakeup exuIdx ${exuIdx}") 337 connectSamePort(wakeUp,wakeUpIn) 338 backendParams.connectWakeup(exuIdx) 339 if (backendParams.isCopyPdest(exuIdx)) { 340 println(s"[Backend] exuIdx ${exuIdx} use pdestCopy ${backendParams.getCopyPdestIndex(exuIdx)}") 341 wakeUp.bits.pdest := wakeUpIn.bits.pdestCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 342 if (wakeUpIn.bits.rfWenCopy.nonEmpty) wakeUp.bits.rfWen := wakeUpIn.bits.rfWenCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 343 if (wakeUpIn.bits.fpWenCopy.nonEmpty) wakeUp.bits.fpWen := wakeUpIn.bits.fpWenCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 344 if (wakeUpIn.bits.vecWenCopy.nonEmpty) wakeUp.bits.vecWen := wakeUpIn.bits.vecWenCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 345 if (wakeUpIn.bits.v0WenCopy.nonEmpty) wakeUp.bits.v0Wen := wakeUpIn.bits.v0WenCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 346 if (wakeUpIn.bits.vlWenCopy.nonEmpty) wakeUp.bits.vlWen := wakeUpIn.bits.vlWenCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 347 if (wakeUpIn.bits.loadDependencyCopy.nonEmpty) wakeUp.bits.loadDependency := wakeUpIn.bits.loadDependencyCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 348 } 349 if (iq.params.numIntSrc == 0) wakeUp.bits.rfWen := false.B 350 if (iq.params.numFpSrc == 0) wakeUp.bits.fpWen := false.B 351 if (iq.params.numVfSrc == 0) wakeUp.bits.vecWen := false.B 352 if (iq.params.numV0Src == 0) wakeUp.bits.v0Wen := false.B 353 if (iq.params.numVlSrc == 0) wakeUp.bits.vlWen := false.B 354 } 355 iq.io.og0Cancel := io.fromDataPath.og0Cancel 356 iq.io.og1Cancel := io.fromDataPath.og1Cancel 357 iq.io.ldCancel := io.ldCancel 358 } 359 360 // connect the vl writeback informatino to the issue queues 361 issueQueues.zipWithIndex.foreach { case(iq, i) => 362 iq.io.vlIsVlmax := io.vlWriteBackInfo.vlIsVlmax 363 iq.io.vlIsZero := io.vlWriteBackInfo.vlIsZero 364 } 365 366 private val iqWakeUpOutMap: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] = 367 issueQueues.flatMap(_.io.wakeupToIQ) 368 .map(x => (x.bits.exuIdx, x)) 369 .toMap 370 371 // Connect bundles having the same wakeup source 372 io.toSchedulers.wakeupVec.foreach { wakeUp => 373 wakeUp := iqWakeUpOutMap(wakeUp.bits.exuIdx) 374 } 375 376 io.toDataPathAfterDelay.zipWithIndex.foreach { case (toDpDy, i) => 377 toDpDy <> issueQueues(i).io.deqDelay 378 } 379 380 // Response 381 issueQueues.zipWithIndex.foreach { case (iq, i) => 382 iq.io.og0Resp.zipWithIndex.foreach { case (og0Resp, j) => 383 og0Resp := io.fromDataPath(i)(j).og0resp 384 } 385 iq.io.og1Resp.zipWithIndex.foreach { case (og1Resp, j) => 386 og1Resp := io.fromDataPath(i)(j).og1resp 387 } 388 iq.io.finalIssueResp.foreach(_.zipWithIndex.foreach { case (finalIssueResp, j) => 389 if (io.loadFinalIssueResp(i).isDefinedAt(j)) { 390 finalIssueResp := io.loadFinalIssueResp(i)(j) 391 } else { 392 finalIssueResp := 0.U.asTypeOf(finalIssueResp) 393 } 394 }) 395 iq.io.memAddrIssueResp.foreach(_.zipWithIndex.foreach { case (memAddrIssueResp, j) => 396 if (io.memAddrIssueResp(i).isDefinedAt(j)) { 397 memAddrIssueResp := io.memAddrIssueResp(i)(j) 398 } else { 399 memAddrIssueResp := 0.U.asTypeOf(memAddrIssueResp) 400 } 401 }) 402 iq.io.vecLoadIssueResp.foreach(_.zipWithIndex.foreach { case (resp, deqIdx) => 403 resp := io.vecLoadIssueResp(i)(deqIdx) 404 }) 405 if(params.isVfSchd) { 406 iq.io.og2Resp.get.zipWithIndex.foreach { case (og2Resp, exuIdx) => 407 og2Resp := io.fromOg2.get(i)(exuIdx) 408 } 409 } 410 iq.io.wbBusyTableRead := io.fromWbFuBusyTable.fuBusyTableRead(i) 411 io.wbFuBusyTable(i) := iq.io.wbBusyTableWrite 412 } 413 414 // perfEvent 415 val lastCycleDp2IqOutFireVec = RegNext(VecInit(dispatch2Iq.io.out.flatten.map(_.fire))) 416 val lastCycleIqEnqFireVec = RegNext(VecInit(issueQueues.map(_.io.enq.map(_.fire)).flatten)) 417 val lastCycleIqFullVec = RegNext(VecInit(issueQueues.map(_.io.enq.head.ready))) 418 419 val issueQueueFullVecPerf = issueQueues.zip(lastCycleIqFullVec)map{ case (iq, full) => (iq.params.getIQName + s"_full", full) } 420 val basePerfEvents = Seq( 421 ("dispatch2Iq_out_fire_cnt", PopCount(lastCycleDp2IqOutFireVec) ), 422 ("issueQueue_enq_fire_cnt", PopCount(lastCycleIqEnqFireVec) ) 423 ) ++ issueQueueFullVecPerf 424 425 println(s"[Scheduler] io.fromSchedulers.wakeupVec: ${io.fromSchedulers.wakeupVec.map(x => backendParams.getExuName(x.bits.exuIdx))}") 426 println(s"[Scheduler] iqWakeUpInKeys: ${iqWakeUpInMap.keys}") 427 428 println(s"[Scheduler] iqWakeUpOutKeys: ${iqWakeUpOutMap.keys}") 429 println(s"[Scheduler] io.toSchedulers.wakeupVec: ${io.toSchedulers.wakeupVec.map(x => backendParams.getExuName(x.bits.exuIdx))}") 430} 431 432class SchedulerArithImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 433 extends SchedulerImpBase(wrapper) 434 with HasXSParameter 435 with HasPerfEvents 436{ 437// dontTouch(io.vfWbFuBusyTable) 438 println(s"[SchedulerArithImp] " + 439 s"has intBusyTable: ${intBusyTable.nonEmpty}, " + 440 s"has vfBusyTable: ${vfBusyTable.nonEmpty}") 441 442 issueQueues.zipWithIndex.foreach { case (iq, i) => 443 iq.io.flush <> io.fromCtrlBlock.flush 444 iq.io.enq <> dispatch2Iq.io.out(i) 445 val intWBIQ = params.schdType match { 446 case IntScheduler() => wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) 447 case FpScheduler() => wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) 448 case VfScheduler() => (wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 449 wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 450 wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1)) 451 case _ => null 452 } 453 iq.io.wakeupFromWB.zip(intWBIQ).foreach{ case (sink, source) => sink := source} 454 } 455 456 val perfEvents = basePerfEvents 457 generatePerfEvent() 458} 459 460// FIXME: Vector mem instructions may not be handled properly! 461class SchedulerMemImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 462 extends SchedulerImpBase(wrapper) 463 with HasXSParameter 464 with HasPerfEvents 465{ 466 println(s"[SchedulerMemImp] " + 467 s"has intBusyTable: ${intBusyTable.nonEmpty}, " + 468 s"has vfBusyTable: ${vfBusyTable.nonEmpty}") 469 470 val memAddrIQs = issueQueues.filter(_.params.isMemAddrIQ) 471 val stAddrIQs = issueQueues.filter(iq => iq.params.StaCnt > 0) // included in memAddrIQs 472 val ldAddrIQs = issueQueues.filter(iq => iq.params.LduCnt > 0) 473 val stDataIQs = issueQueues.filter(iq => iq.params.StdCnt > 0) 474 val vecMemIQs = issueQueues.filter(_.params.isVecMemIQ) 475 val (hyuIQs, hyuIQIdxs) = issueQueues.zipWithIndex.filter(_._1.params.HyuCnt > 0).unzip 476 477 println(s"[SchedulerMemImp] memAddrIQs.size: ${memAddrIQs.size}, enq.size: ${memAddrIQs.map(_.io.enq.size).sum}") 478 println(s"[SchedulerMemImp] stAddrIQs.size: ${stAddrIQs.size }, enq.size: ${stAddrIQs.map(_.io.enq.size).sum}") 479 println(s"[SchedulerMemImp] ldAddrIQs.size: ${ldAddrIQs.size }, enq.size: ${ldAddrIQs.map(_.io.enq.size).sum}") 480 println(s"[SchedulerMemImp] stDataIQs.size: ${stDataIQs.size }, enq.size: ${stDataIQs.map(_.io.enq.size).sum}") 481 println(s"[SchedulerMemImp] hyuIQs.size: ${hyuIQs.size }, enq.size: ${hyuIQs.map(_.io.enq.size).sum}") 482 require(memAddrIQs.nonEmpty && stDataIQs.nonEmpty) 483 484 io.toMem.get.loadFastMatch := 0.U.asTypeOf(io.toMem.get.loadFastMatch) // TODO: is still needed? 485 486 private val loadWakeUp = issueQueues.filter(_.params.LdExuCnt > 0).map(_.asInstanceOf[IssueQueueMemAddrImp].io.memIO.get.loadWakeUp).flatten 487 require(loadWakeUp.length == io.fromMem.get.wakeup.length) 488 loadWakeUp.zip(io.fromMem.get.wakeup).foreach(x => x._1 := x._2) 489 490 memAddrIQs.zipWithIndex.foreach { case (iq, i) => 491 iq.io.flush <> io.fromCtrlBlock.flush 492 iq.io.enq <> dispatch2Iq.io.out(i) 493 iq.io.wakeupFromWB.zip( 494 wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 495 wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 496 wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 497 wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 498 wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1) 499 ).foreach{ case (sink, source) => sink := source} 500 } 501 502 ldAddrIQs.zipWithIndex.foreach { 503 case (imp: IssueQueueMemAddrImp, i) => 504 imp.io.memIO.get.feedbackIO.head := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO.head) 505 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 506 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 507 case _ => 508 } 509 510 stAddrIQs.zipWithIndex.foreach { 511 case (imp: IssueQueueMemAddrImp, i) => 512 imp.io.memIO.get.feedbackIO.head := io.fromMem.get.staFeedback(i) 513 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 514 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 515 case _ => 516 } 517 518 hyuIQs.zip(hyuIQIdxs).foreach { 519 case (imp: IssueQueueMemAddrImp, idx) => 520 imp.io.memIO.get.feedbackIO.head := io.fromMem.get.hyuFeedback.head 521 imp.io.memIO.get.feedbackIO(1) := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO(1)) 522 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 523 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 524 // TODO: refactor ditry code 525 imp.io.deqDelay(1).ready := false.B 526 io.toDataPathAfterDelay(idx)(1).valid := false.B 527 io.toDataPathAfterDelay(idx)(1).bits := 0.U.asTypeOf(io.toDataPathAfterDelay(idx)(1).bits) 528 case _ => 529 } 530 531 private val staIdxSeq = (stAddrIQs).map(iq => iq.params.idxInSchBlk) 532 private val hyaIdxSeq = (hyuIQs).map(iq => iq.params.idxInSchBlk) 533 534 println(s"[SchedulerMemImp] sta iq idx in memSchdBlock: $staIdxSeq") 535 println(s"[SchedulerMemImp] hya iq idx in memSchdBlock: $hyaIdxSeq") 536 537 private val staEnqs = stAddrIQs.map(_.io.enq).flatten 538 private val stdEnqs = stDataIQs.map(_.io.enq).flatten.take(staEnqs.size) 539 private val hyaEnqs = hyuIQs.map(_.io.enq).flatten 540 private val hydEnqs = stDataIQs.map(_.io.enq).flatten.drop(staEnqs.size) 541 542 require(staEnqs.size == stdEnqs.size, s"number of enq ports of store address IQs(${staEnqs.size}) " + 543 s"should be equal to number of enq ports of store data IQs(${stdEnqs.size})") 544 545 require(hyaEnqs.size == hydEnqs.size, s"number of enq ports of hybrid address IQs(${hyaEnqs.size}) " + 546 s"should be equal to number of enq ports of hybrid data IQs(${hydEnqs.size})") 547 548 val d2IqStaOut = dispatch2Iq.io.out.zipWithIndex.filter(staIdxSeq contains _._2).unzip._1.flatten 549 d2IqStaOut.zip(staEnqs).zip(stdEnqs).foreach{ case((dp, staIQ), stdIQ) => 550 val isAllReady = staIQ.ready && stdIQ.ready 551 dp.ready := isAllReady 552 staIQ.valid := dp.valid && isAllReady 553 stdIQ.valid := dp.valid && isAllReady && FuType.FuTypeOrR(dp.bits.fuType, FuType.stu, FuType.mou) 554 } 555 556 val d2IqHyaOut = dispatch2Iq.io.out.zipWithIndex.filter(hyaIdxSeq contains _._2).unzip._1.flatten 557 d2IqHyaOut.zip(hyaEnqs).zip(hydEnqs).foreach{ case((dp, hyaIQ), hydIQ) => 558 val isAllReady = hyaIQ.ready && hydIQ.ready 559 dp.ready := isAllReady 560 hyaIQ.valid := dp.valid && isAllReady 561 hydIQ.valid := dp.valid && isAllReady && FuType.FuTypeOrR(dp.bits.fuType, FuType.stu, FuType.mou) 562 } 563 564 stDataIQs.zipWithIndex.foreach { case (iq, i) => 565 iq.io.flush <> io.fromCtrlBlock.flush 566 iq.io.wakeupFromWB.zip( 567 wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 568 wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 569 wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 570 wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 571 wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 572 ).foreach{ case (sink, source) => sink := source} 573 } 574 575 (stdEnqs ++ hydEnqs).zip(staEnqs ++ hyaEnqs).zipWithIndex.foreach { case ((stdIQEnq, staIQEnq), i) => 576 stdIQEnq.bits := staIQEnq.bits 577 // Store data reuses store addr src(1) in dispatch2iq 578 // [dispatch2iq] --src*------src*(0)--> [staIQ|hyaIQ] 579 // \ 580 // ---src*(1)--> [stdIQ] 581 // Since the src(1) of sta is easier to get, stdIQEnq.bits.src*(0) is assigned to staIQEnq.bits.src*(1) 582 // instead of dispatch2Iq.io.out(x).bits.src*(1) 583 val stdIdx = 1 584 stdIQEnq.bits.srcState(0) := staIQEnq.bits.srcState(stdIdx) 585 stdIQEnq.bits.srcLoadDependency(0) := staIQEnq.bits.srcLoadDependency(1) 586 stdIQEnq.bits.srcType(0) := staIQEnq.bits.srcType(stdIdx) 587 stdIQEnq.bits.psrc(0) := staIQEnq.bits.psrc(stdIdx) 588 stdIQEnq.bits.sqIdx := staIQEnq.bits.sqIdx 589 } 590 591 vecMemIQs.foreach { 592 case imp: IssueQueueVecMemImp => 593 imp.io.memIO.get.sqDeqPtr.foreach(_ := io.fromMem.get.sqDeqPtr) 594 imp.io.memIO.get.lqDeqPtr.foreach(_ := io.fromMem.get.lqDeqPtr) 595 // not used 596 //imp.io.memIO.get.feedbackIO.head := io.fromMem.get.vstuFeedback.head // only vector store replay 597 // maybe not used 598 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 599 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 600 imp.io.wakeupFromWB.zip( 601 wakeupFromIntWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 602 wakeupFromFpWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 603 wakeupFromVfWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 604 wakeupFromV0WBVec.zipWithIndex.filter(x => imp.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 605 wakeupFromVlWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 606 ).foreach{ case (sink, source) => sink := source} 607 608 case _ => 609 } 610 val vecMemFeedbackIO: Seq[MemRSFeedbackIO] = vecMemIQs.map { 611 case imp: IssueQueueVecMemImp => 612 imp.io.memIO.get.feedbackIO 613 }.flatten 614 assert(vecMemFeedbackIO.size == io.fromMem.get.vstuFeedback.size, "vecMemFeedback size dont match!") 615 vecMemFeedbackIO.zip(io.fromMem.get.vstuFeedback).foreach{ 616 case (sink, source) => 617 sink := source 618 } 619 620 val lsqEnqCtrl = Module(new LsqEnqCtrl) 621 622 lsqEnqCtrl.io.redirect <> io.fromCtrlBlock.flush 623 lsqEnqCtrl.io.enq <> dispatch2Iq.io.enqLsqIO.get 624 lsqEnqCtrl.io.lcommit := io.fromMem.get.lcommit 625 lsqEnqCtrl.io.scommit := io.fromMem.get.scommit 626 lsqEnqCtrl.io.lqCancelCnt := io.fromMem.get.lqCancelCnt 627 lsqEnqCtrl.io.sqCancelCnt := io.fromMem.get.sqCancelCnt 628 dispatch2Iq.io.lqFreeCount.get := lsqEnqCtrl.io.lqFreeCount 629 dispatch2Iq.io.sqFreeCount.get := lsqEnqCtrl.io.sqFreeCount 630 io.memIO.get.lsqEnqIO <> lsqEnqCtrl.io.enqLsq 631 632 dontTouch(io.vecLoadIssueResp) 633 634 val intBusyTablePerf = intBusyTable.get 635 val fpBusyTablePerf = fpBusyTable.get 636 val vecBusyTablePerf = vfBusyTable.get 637 val v0BusyTablePerf = v0BusyTable.get 638 val vlBusyTablePerf = vlBusyTable.get 639 640 val perfEvents = basePerfEvents ++ Seq(intBusyTablePerf, fpBusyTablePerf, vecBusyTablePerf, v0BusyTablePerf, vlBusyTablePerf).flatten(_.getPerfEvents) 641 generatePerfEvent() 642} 643