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