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