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 fromOg2Resp = if(params.needOg2Resp) Some(MixedVec(params.issueBlockParams.filter(_.needOg2Resp).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 if (iq.params.needLoadDependency) 380 iq.io.ldCancel := io.ldCancel 381 else 382 iq.io.ldCancel := 0.U.asTypeOf(io.ldCancel) 383 } 384 385 // connect the vl writeback informatino to the issue queues 386 issueQueues.zipWithIndex.foreach { case(iq, i) => 387 iq.io.vlIsVlmax := io.vlWriteBackInfo.vlIsVlmax 388 iq.io.vlIsZero := io.vlWriteBackInfo.vlIsZero 389 } 390 391 private val iqWakeUpOutMap: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] = 392 issueQueues.flatMap(_.io.wakeupToIQ) 393 .map(x => (x.bits.exuIdx, x)) 394 .toMap 395 396 // Connect bundles having the same wakeup source 397 io.toSchedulers.wakeupVec.foreach { wakeUp => 398 wakeUp := iqWakeUpOutMap(wakeUp.bits.exuIdx) 399 } 400 401 io.toDataPathAfterDelay.zipWithIndex.foreach { case (toDpDy, i) => 402 toDpDy <> issueQueues(i).io.deqDelay 403 } 404 405 // Response 406 issueQueues.zipWithIndex.foreach { case (iq, i) => 407 iq.io.og0Resp.zipWithIndex.foreach { case (og0Resp, j) => 408 og0Resp := io.fromDataPath(i)(j).og0resp 409 } 410 iq.io.og1Resp.zipWithIndex.foreach { case (og1Resp, j) => 411 og1Resp := io.fromDataPath(i)(j).og1resp 412 } 413 iq.io.finalIssueResp.foreach(_.zipWithIndex.foreach { case (finalIssueResp, j) => 414 if (io.loadFinalIssueResp(i).isDefinedAt(j)) { 415 finalIssueResp := io.loadFinalIssueResp(i)(j) 416 } else { 417 finalIssueResp := 0.U.asTypeOf(finalIssueResp) 418 } 419 }) 420 iq.io.memAddrIssueResp.foreach(_.zipWithIndex.foreach { case (memAddrIssueResp, j) => 421 if (io.memAddrIssueResp(i).isDefinedAt(j)) { 422 memAddrIssueResp := io.memAddrIssueResp(i)(j) 423 } else { 424 memAddrIssueResp := 0.U.asTypeOf(memAddrIssueResp) 425 } 426 }) 427 iq.io.vecLoadIssueResp.foreach(_.zipWithIndex.foreach { case (resp, deqIdx) => 428 resp := io.vecLoadIssueResp(i)(deqIdx) 429 }) 430 iq.io.wbBusyTableRead := io.fromWbFuBusyTable.fuBusyTableRead(i) 431 io.wbFuBusyTable(i) := iq.io.wbBusyTableWrite 432 iq.io.replaceRCIdx.foreach(x => x := 0.U.asTypeOf(x)) 433 } 434 if (params.needOg2Resp) { 435 issueQueues.filter(_.params.needOg2Resp).zip(io.fromOg2Resp.get).foreach{ case (iq, og2RespVec) => 436 iq.io.og2Resp.get.zip(og2RespVec).foreach{ case (iqOg2Resp, og2Resp) => 437 iqOg2Resp := og2Resp 438 } 439 } 440 } 441 442 // Connect each replace RCIdx to IQ 443 if (params.needWriteRegCache) { 444 val iqReplaceRCIdxVec = issueQueues.filter(_.params.needWriteRegCache).flatMap{ iq => 445 iq.params.allExuParams.zip(iq.io.replaceRCIdx.get).filter(_._1.needWriteRegCache).map(_._2) 446 } 447 iqReplaceRCIdxVec.zip(io.fromDataPath.replaceRCIdx.get).foreach{ case (iq, in) => 448 iq := in 449 } 450 451 println(s"[Scheduler] numWriteRegCache: ${params.numWriteRegCache}") 452 println(s"[Scheduler] iqReplaceRCIdxVec: ${iqReplaceRCIdxVec.size}") 453 } 454 455 // perfEvent 456 val lastCycleDp2IqOutFireVec = RegNext(VecInit(dispatch2Iq.io.out.flatten.map(_.fire))) 457 val lastCycleIqEnqFireVec = RegNext(VecInit(issueQueues.map(_.io.enq.map(_.fire)).flatten)) 458 val lastCycleIqFullVec = RegNext(VecInit(issueQueues.map(_.io.enq.head.ready))) 459 460 val issueQueueFullVecPerf = issueQueues.zip(lastCycleIqFullVec)map{ case (iq, full) => (iq.params.getIQName + s"_full", full) } 461 val basePerfEvents = Seq( 462 ("dispatch2Iq_out_fire_cnt", PopCount(lastCycleDp2IqOutFireVec) ), 463 ("issueQueue_enq_fire_cnt", PopCount(lastCycleIqEnqFireVec) ) 464 ) ++ issueQueueFullVecPerf 465 466 println(s"[Scheduler] io.fromSchedulers.wakeupVec: ${io.fromSchedulers.wakeupVec.map(x => backendParams.getExuName(x.bits.exuIdx))}") 467 println(s"[Scheduler] iqWakeUpInKeys: ${iqWakeUpInMap.keys}") 468 469 println(s"[Scheduler] iqWakeUpOutKeys: ${iqWakeUpOutMap.keys}") 470 println(s"[Scheduler] io.toSchedulers.wakeupVec: ${io.toSchedulers.wakeupVec.map(x => backendParams.getExuName(x.bits.exuIdx))}") 471} 472 473class SchedulerArithImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 474 extends SchedulerImpBase(wrapper) 475 with HasXSParameter 476 with HasPerfEvents 477{ 478// dontTouch(io.vfWbFuBusyTable) 479 println(s"[SchedulerArithImp] " + 480 s"has intBusyTable: ${intBusyTable.nonEmpty}, " + 481 s"has vfBusyTable: ${vfBusyTable.nonEmpty}") 482 483 issueQueues.zipWithIndex.foreach { case (iq, i) => 484 iq.io.flush <> io.fromCtrlBlock.flush 485 iq.io.enq <> dispatch2Iq.io.out(i) 486 if (!iq.params.needLoadDependency) { 487 iq.io.enq.map(x => x.bits.srcLoadDependency := 0.U.asTypeOf(x.bits.srcLoadDependency)) 488 } 489 val intWBIQ = params.schdType match { 490 case IntScheduler() => wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) 491 case FpScheduler() => wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) 492 case VfScheduler() => (wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 493 wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 494 wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1)) 495 case _ => null 496 } 497 iq.io.wakeupFromWB.zip(intWBIQ).foreach{ case (sink, source) => sink := source} 498 } 499 500 val perfEvents = basePerfEvents 501 generatePerfEvent() 502} 503 504// FIXME: Vector mem instructions may not be handled properly! 505class SchedulerMemImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 506 extends SchedulerImpBase(wrapper) 507 with HasXSParameter 508 with HasPerfEvents 509{ 510 println(s"[SchedulerMemImp] " + 511 s"has intBusyTable: ${intBusyTable.nonEmpty}, " + 512 s"has vfBusyTable: ${vfBusyTable.nonEmpty}") 513 514 val memAddrIQs = issueQueues.filter(_.params.isMemAddrIQ) 515 val stAddrIQs = issueQueues.filter(iq => iq.params.StaCnt > 0) // included in memAddrIQs 516 val ldAddrIQs = issueQueues.filter(iq => iq.params.LduCnt > 0) 517 val stDataIQs = issueQueues.filter(iq => iq.params.StdCnt > 0) 518 val vecMemIQs = issueQueues.filter(_.params.isVecMemIQ) 519 val (hyuIQs, hyuIQIdxs) = issueQueues.zipWithIndex.filter(_._1.params.HyuCnt > 0).unzip 520 521 println(s"[SchedulerMemImp] memAddrIQs.size: ${memAddrIQs.size}, enq.size: ${memAddrIQs.map(_.io.enq.size).sum}") 522 println(s"[SchedulerMemImp] stAddrIQs.size: ${stAddrIQs.size }, enq.size: ${stAddrIQs.map(_.io.enq.size).sum}") 523 println(s"[SchedulerMemImp] ldAddrIQs.size: ${ldAddrIQs.size }, enq.size: ${ldAddrIQs.map(_.io.enq.size).sum}") 524 println(s"[SchedulerMemImp] stDataIQs.size: ${stDataIQs.size }, enq.size: ${stDataIQs.map(_.io.enq.size).sum}") 525 println(s"[SchedulerMemImp] hyuIQs.size: ${hyuIQs.size }, enq.size: ${hyuIQs.map(_.io.enq.size).sum}") 526 require(memAddrIQs.nonEmpty && stDataIQs.nonEmpty) 527 528 io.toMem.get.loadFastMatch := 0.U.asTypeOf(io.toMem.get.loadFastMatch) // TODO: is still needed? 529 530 private val loadWakeUp = issueQueues.filter(_.params.LdExuCnt > 0).map(_.asInstanceOf[IssueQueueMemAddrImp].io.memIO.get.loadWakeUp).flatten 531 require(loadWakeUp.length == io.fromMem.get.wakeup.length) 532 loadWakeUp.zip(io.fromMem.get.wakeup).foreach(x => x._1 := x._2) 533 534 memAddrIQs.zipWithIndex.foreach { case (iq, i) => 535 iq.io.flush <> io.fromCtrlBlock.flush 536 iq.io.enq <> dispatch2Iq.io.out(i) 537 if (!iq.params.needLoadDependency) { 538 iq.io.enq.map(x => x.bits.srcLoadDependency := 0.U.asTypeOf(x.bits.srcLoadDependency)) 539 } 540 iq.io.wakeupFromWB.zip( 541 wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 542 wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 543 wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 544 wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 545 wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1) 546 ).foreach{ case (sink, source) => sink := source} 547 } 548 549 ldAddrIQs.zipWithIndex.foreach { 550 case (imp: IssueQueueMemAddrImp, i) => 551 imp.io.memIO.get.feedbackIO.head := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO.head) 552 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 553 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 554 case _ => 555 } 556 557 stAddrIQs.zipWithIndex.foreach { 558 case (imp: IssueQueueMemAddrImp, i) => 559 imp.io.memIO.get.feedbackIO.head := io.fromMem.get.staFeedback(i) 560 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 561 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 562 case _ => 563 } 564 565 hyuIQs.zip(hyuIQIdxs).foreach { 566 case (imp: IssueQueueMemAddrImp, idx) => 567 imp.io.memIO.get.feedbackIO.head := io.fromMem.get.hyuFeedback.head 568 imp.io.memIO.get.feedbackIO(1) := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO(1)) 569 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 570 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 571 // TODO: refactor ditry code 572 imp.io.deqDelay(1).ready := false.B 573 io.toDataPathAfterDelay(idx)(1).valid := false.B 574 io.toDataPathAfterDelay(idx)(1).bits := 0.U.asTypeOf(io.toDataPathAfterDelay(idx)(1).bits) 575 case _ => 576 } 577 578 private val staIdxSeq = (stAddrIQs).map(iq => iq.params.idxInSchBlk) 579 private val hyaIdxSeq = (hyuIQs).map(iq => iq.params.idxInSchBlk) 580 581 println(s"[SchedulerMemImp] sta iq idx in memSchdBlock: $staIdxSeq") 582 println(s"[SchedulerMemImp] hya iq idx in memSchdBlock: $hyaIdxSeq") 583 584 private val staEnqs = stAddrIQs.map(_.io.enq).flatten 585 private val stdEnqs = stDataIQs.map(_.io.enq).flatten.take(staEnqs.size) 586 private val hyaEnqs = hyuIQs.map(_.io.enq).flatten 587 private val hydEnqs = stDataIQs.map(_.io.enq).flatten.drop(staEnqs.size) 588 589 require(staEnqs.size == stdEnqs.size, s"number of enq ports of store address IQs(${staEnqs.size}) " + 590 s"should be equal to number of enq ports of store data IQs(${stdEnqs.size})") 591 592 require(hyaEnqs.size == hydEnqs.size, s"number of enq ports of hybrid address IQs(${hyaEnqs.size}) " + 593 s"should be equal to number of enq ports of hybrid data IQs(${hydEnqs.size})") 594 595 val d2IqStaOut = dispatch2Iq.io.out.zipWithIndex.filter(staIdxSeq contains _._2).unzip._1.flatten 596 d2IqStaOut.zip(staEnqs).zip(stdEnqs).foreach{ case((dp, staIQ), stdIQ) => 597 val isAllReady = staIQ.ready && stdIQ.ready 598 dp.ready := isAllReady 599 staIQ.valid := dp.valid && isAllReady 600 stdIQ.valid := dp.valid && isAllReady && FuType.FuTypeOrR(dp.bits.fuType, FuType.stu, FuType.mou) 601 } 602 603 val d2IqHyaOut = dispatch2Iq.io.out.zipWithIndex.filter(hyaIdxSeq contains _._2).unzip._1.flatten 604 d2IqHyaOut.zip(hyaEnqs).zip(hydEnqs).foreach{ case((dp, hyaIQ), hydIQ) => 605 val isAllReady = hyaIQ.ready && hydIQ.ready 606 dp.ready := isAllReady 607 hyaIQ.valid := dp.valid && isAllReady 608 hydIQ.valid := dp.valid && isAllReady && FuType.FuTypeOrR(dp.bits.fuType, FuType.stu, FuType.mou) 609 } 610 611 stDataIQs.zipWithIndex.foreach { case (iq, i) => 612 iq.io.flush <> io.fromCtrlBlock.flush 613 iq.io.wakeupFromWB.zip( 614 wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 615 wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 616 wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 617 wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 618 wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 619 ).foreach{ case (sink, source) => sink := source} 620 } 621 622 (stdEnqs ++ hydEnqs).zip(staEnqs ++ hyaEnqs).zipWithIndex.foreach { case ((stdIQEnq, staIQEnq), i) => 623 stdIQEnq.bits := staIQEnq.bits 624 // Store data reuses store addr src(1) in dispatch2iq 625 // [dispatch2iq] --src*------src*(0)--> [staIQ|hyaIQ] 626 // \ 627 // ---src*(1)--> [stdIQ] 628 // Since the src(1) of sta is easier to get, stdIQEnq.bits.src*(0) is assigned to staIQEnq.bits.src*(1) 629 // instead of dispatch2Iq.io.out(x).bits.src*(1) 630 val stdIdx = 1 631 stdIQEnq.bits.srcState(0) := staIQEnq.bits.srcState(stdIdx) 632 stdIQEnq.bits.srcLoadDependency(0) := staIQEnq.bits.srcLoadDependency(stdIdx) 633 stdIQEnq.bits.srcType(0) := staIQEnq.bits.srcType(stdIdx) 634 stdIQEnq.bits.psrc(0) := staIQEnq.bits.psrc(stdIdx) 635 stdIQEnq.bits.sqIdx := staIQEnq.bits.sqIdx 636 stdIQEnq.bits.useRegCache(0) := staIQEnq.bits.useRegCache(stdIdx) 637 stdIQEnq.bits.regCacheIdx(0) := staIQEnq.bits.regCacheIdx(stdIdx) 638 } 639 640 vecMemIQs.foreach { 641 case imp: IssueQueueVecMemImp => 642 imp.io.memIO.get.sqDeqPtr.foreach(_ := io.fromMem.get.sqDeqPtr) 643 imp.io.memIO.get.lqDeqPtr.foreach(_ := io.fromMem.get.lqDeqPtr) 644 // not used 645 //imp.io.memIO.get.feedbackIO.head := io.fromMem.get.vstuFeedback.head // only vector store replay 646 // maybe not used 647 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 648 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 649 imp.io.wakeupFromWB.zip( 650 wakeupFromIntWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 651 wakeupFromFpWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 652 wakeupFromVfWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 653 wakeupFromV0WBVec.zipWithIndex.filter(x => imp.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 654 wakeupFromVlWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 655 ).foreach{ case (sink, source) => sink := source} 656 657 case _ => 658 } 659 val vecMemFeedbackIO: Seq[MemRSFeedbackIO] = vecMemIQs.map { 660 case imp: IssueQueueVecMemImp => 661 imp.io.memIO.get.feedbackIO 662 }.flatten 663 assert(vecMemFeedbackIO.size == io.fromMem.get.vstuFeedback.size, "vecMemFeedback size dont match!") 664 vecMemFeedbackIO.zip(io.fromMem.get.vstuFeedback).foreach{ 665 case (sink, source) => 666 sink := source 667 } 668 669 val lsqEnqCtrl = Module(new LsqEnqCtrl) 670 671 lsqEnqCtrl.io.redirect <> io.fromCtrlBlock.flush 672 lsqEnqCtrl.io.enq <> dispatch2Iq.io.enqLsqIO.get 673 lsqEnqCtrl.io.lcommit := io.fromMem.get.lcommit 674 lsqEnqCtrl.io.scommit := io.fromMem.get.scommit 675 lsqEnqCtrl.io.lqCancelCnt := io.fromMem.get.lqCancelCnt 676 lsqEnqCtrl.io.sqCancelCnt := io.fromMem.get.sqCancelCnt 677 dispatch2Iq.io.lqFreeCount.get := lsqEnqCtrl.io.lqFreeCount 678 dispatch2Iq.io.sqFreeCount.get := lsqEnqCtrl.io.sqFreeCount 679 io.memIO.get.lsqEnqIO <> lsqEnqCtrl.io.enqLsq 680 681 dontTouch(io.vecLoadIssueResp) 682 683 val intBusyTablePerf = intBusyTable.get 684 val fpBusyTablePerf = fpBusyTable.get 685 val vecBusyTablePerf = vfBusyTable.get 686 val v0BusyTablePerf = v0BusyTable.get 687 val vlBusyTablePerf = vlBusyTable.get 688 689 val perfEvents = basePerfEvents ++ Seq(intBusyTablePerf, fpBusyTablePerf, vecBusyTablePerf, v0BusyTablePerf, vlBusyTablePerf).flatten(_.getPerfEvents) 690 generatePerfEvent() 691} 692