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