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