1730cfbc0SXuan Hupackage xiangshan.backend.issue 2730cfbc0SXuan Hu 3730cfbc0SXuan Huimport chipsalliance.rocketchip.config.Parameters 4730cfbc0SXuan Huimport chisel3._ 5730cfbc0SXuan Huimport chisel3.util._ 6730cfbc0SXuan Huimport freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 7730cfbc0SXuan Huimport xiangshan._ 8730cfbc0SXuan Huimport xiangshan.backend.Bundles 9730cfbc0SXuan Huimport xiangshan.backend.datapath.DataConfig.VAddrData 10730cfbc0SXuan Huimport xiangshan.backend.regfile.RfWritePortWithConfig 11730cfbc0SXuan Huimport xiangshan.backend.rename.BusyTable 12730cfbc0SXuan Huimport xiangshan.mem.{LsqEnqCtrl, LsqEnqIO, MemWaitUpdateReq, SqPtr} 13730cfbc0SXuan Huimport xiangshan.backend.Bundles.{DynInst, IssueQueueWakeUpBundle} 14730cfbc0SXuan Hu 15730cfbc0SXuan Husealed trait SchedulerType 16730cfbc0SXuan Hu 17730cfbc0SXuan Hucase class IntScheduler() extends SchedulerType 18730cfbc0SXuan Hucase class MemScheduler() extends SchedulerType 19730cfbc0SXuan Hucase class VfScheduler() extends SchedulerType 20730cfbc0SXuan Hucase class NoScheduler() extends SchedulerType 21730cfbc0SXuan Hu 22730cfbc0SXuan Huclass Scheduler(val params: SchdBlockParams)(implicit p: Parameters) extends LazyModule with HasXSParameter { 23730cfbc0SXuan Hu val numIntStateWrite = backendParams.numIntWb 24730cfbc0SXuan Hu val numVfStateWrite = backendParams.numVfWb 25730cfbc0SXuan Hu 26730cfbc0SXuan Hu val dispatch2Iq = LazyModule(new Dispatch2Iq(params)) 27730cfbc0SXuan Hu val issueQueue = params.issueBlockParams.map(x => LazyModule(new IssueQueue(x).suggestName(x.getIQName))) 28730cfbc0SXuan Hu 29730cfbc0SXuan Hu lazy val module = params.schdType match { 30730cfbc0SXuan Hu case IntScheduler() => new SchedulerArithImp(this)(params, p) 31730cfbc0SXuan Hu case MemScheduler() => new SchedulerMemImp(this)(params, p) 32730cfbc0SXuan Hu case VfScheduler() => new SchedulerArithImp(this)(params, p) 33730cfbc0SXuan Hu case _ => null 34730cfbc0SXuan Hu } 35730cfbc0SXuan Hu} 36730cfbc0SXuan Hu 37730cfbc0SXuan Huclass SchedulerIO()(implicit params: SchdBlockParams, p: Parameters) extends XSBundle { 3868d13085SXuan Hu // params alias 3968d13085SXuan Hu private val LoadQueueSize = VirtualLoadQueueSize 4068d13085SXuan Hu 41730cfbc0SXuan Hu val fromTop = new Bundle { 42730cfbc0SXuan Hu val hartId = Input(UInt(8.W)) 43730cfbc0SXuan Hu } 44730cfbc0SXuan Hu val fromCtrlBlock = new Bundle { 45730cfbc0SXuan Hu val pcVec = Input(Vec(params.numPcReadPort, UInt(VAddrData().dataWidth.W))) 46730cfbc0SXuan Hu val targetVec = Input(Vec(params.numPcReadPort, UInt(VAddrData().dataWidth.W))) 47730cfbc0SXuan Hu val flush = Flipped(ValidIO(new Redirect)) 48730cfbc0SXuan Hu } 49730cfbc0SXuan Hu val fromDispatch = new Bundle { 50730cfbc0SXuan Hu val allocPregs = Vec(RenameWidth, Input(new ResetPregStateReq)) 51730cfbc0SXuan Hu val uops = Vec(params.numUopIn, Flipped(DecoupledIO(new DynInst))) 52730cfbc0SXuan Hu } 53730cfbc0SXuan Hu val intWriteBack = MixedVec(Vec(backendParams.intPregParams.numWrite, 54730cfbc0SXuan Hu new RfWritePortWithConfig(backendParams.intPregParams.dataCfg, backendParams.intPregParams.addrWidth))) 55730cfbc0SXuan Hu val vfWriteBack = MixedVec(Vec(backendParams.vfPregParams.numWrite, 56730cfbc0SXuan Hu new RfWritePortWithConfig(backendParams.vfPregParams.dataCfg, backendParams.vfPregParams.addrWidth))) 57730cfbc0SXuan Hu val toDataPath: MixedVec[MixedVec[DecoupledIO[Bundles.IssueQueueIssueBundle]]] = MixedVec(params.issueBlockParams.map(_.genIssueDecoupledBundle)) 58730cfbc0SXuan Hu val fromDataPath: MixedVec[MixedVec[Bundles.OGRespBundle]] = MixedVec(params.issueBlockParams.map(x => Flipped(x.genOGRespBundle))) 59730cfbc0SXuan Hu 60730cfbc0SXuan Hu val memIO = if (params.isMemSchd) Some(new Bundle { 61730cfbc0SXuan Hu val lsqEnqIO = Flipped(new LsqEnqIO) 62730cfbc0SXuan Hu }) else None 63730cfbc0SXuan Hu val fromMem = if (params.isMemSchd) Some(new Bundle { 64*7b753bebSXuan Hu val ldaFeedback = Flipped(Vec(params.LduCnt, new MemRSFeedbackIO)) 65*7b753bebSXuan Hu val staFeedback = Flipped(Vec(params.StaCnt, new MemRSFeedbackIO)) 66730cfbc0SXuan Hu val stIssuePtr = Input(new SqPtr()) 67730cfbc0SXuan Hu val lcommit = Input(UInt(log2Up(CommitWidth + 1).W)) 68730cfbc0SXuan Hu val scommit = Input(UInt(log2Ceil(EnsbufferWidth + 1).W)) // connected to `memBlock.io.sqDeq` instead of ROB 69730cfbc0SXuan Hu // from lsq 70730cfbc0SXuan Hu val lqCancelCnt = Input(UInt(log2Up(LoadQueueSize + 1).W)) 71730cfbc0SXuan Hu val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W)) 72730cfbc0SXuan Hu val memWaitUpdateReq = Flipped(new MemWaitUpdateReq) 73730cfbc0SXuan Hu }) else None 74730cfbc0SXuan Hu val toMem = if (params.isMemSchd) Some(new Bundle { 75730cfbc0SXuan Hu val loadFastMatch = Output(Vec(params.LduCnt, new IssueQueueLoadBundle)) 76730cfbc0SXuan Hu }) else None 77730cfbc0SXuan Hu} 78730cfbc0SXuan Hu 79730cfbc0SXuan Huabstract class SchedulerImpBase(wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 80730cfbc0SXuan Hu extends LazyModuleImp(wrapper) 81730cfbc0SXuan Hu with HasXSParameter 82730cfbc0SXuan Hu{ 83730cfbc0SXuan Hu val io = IO(new SchedulerIO()) 84730cfbc0SXuan Hu 85730cfbc0SXuan Hu // alias 86730cfbc0SXuan Hu private val schdType = params.schdType 87730cfbc0SXuan Hu private val (numRfRead, numRfWrite) = params.numRfReadWrite.getOrElse((0, 0)) 88730cfbc0SXuan Hu private val numPregs = params.numPregs 89730cfbc0SXuan Hu 90730cfbc0SXuan Hu // Modules 91730cfbc0SXuan Hu val dispatch2Iq: Dispatch2IqImp = wrapper.dispatch2Iq.module 92730cfbc0SXuan Hu val issueQueues: Seq[IssueQueueImp] = wrapper.issueQueue.map(_.module) 93730cfbc0SXuan Hu 94730cfbc0SXuan Hu // BusyTable Modules 95730cfbc0SXuan Hu val intBusyTable = schdType match { 96730cfbc0SXuan Hu case IntScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numIntStateRead, wrapper.numIntStateWrite))) 97730cfbc0SXuan Hu case _ => None 98730cfbc0SXuan Hu } 99730cfbc0SXuan Hu 100730cfbc0SXuan Hu val vfBusyTable = schdType match { 101730cfbc0SXuan Hu case VfScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numVfStateRead, wrapper.numVfStateWrite))) 102730cfbc0SXuan Hu case _ => None 103730cfbc0SXuan Hu } 104730cfbc0SXuan Hu 105730cfbc0SXuan Hu dispatch2Iq.io match { case dp2iq => 106730cfbc0SXuan Hu dp2iq.redirect <> io.fromCtrlBlock.flush 107730cfbc0SXuan Hu dp2iq.in <> io.fromDispatch.uops 108730cfbc0SXuan Hu dp2iq.readIntState.foreach(_ <> intBusyTable.get.io.read) 109730cfbc0SXuan Hu dp2iq.readVfState.foreach(_ <> vfBusyTable.get.io.read) 110730cfbc0SXuan Hu } 111730cfbc0SXuan Hu 112730cfbc0SXuan Hu intBusyTable match { 113730cfbc0SXuan Hu case Some(bt) => 114730cfbc0SXuan Hu bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) => 115730cfbc0SXuan Hu btAllocPregs.valid := dpAllocPregs.isInt 116730cfbc0SXuan Hu btAllocPregs.bits := dpAllocPregs.preg 117730cfbc0SXuan Hu } 118730cfbc0SXuan Hu bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) => 119730cfbc0SXuan Hu wb.valid := io.intWriteBack(i).wen && io.intWriteBack(i).intWen 120730cfbc0SXuan Hu wb.bits := io.intWriteBack(i).addr 121730cfbc0SXuan Hu } 122730cfbc0SXuan Hu case None => 123730cfbc0SXuan Hu } 124730cfbc0SXuan Hu 125730cfbc0SXuan Hu vfBusyTable match { 126730cfbc0SXuan Hu case Some(bt) => 127730cfbc0SXuan Hu bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) => 128730cfbc0SXuan Hu btAllocPregs.valid := dpAllocPregs.isFp 129730cfbc0SXuan Hu btAllocPregs.bits := dpAllocPregs.preg 130730cfbc0SXuan Hu } 131730cfbc0SXuan Hu bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) => 132730cfbc0SXuan Hu wb.valid := io.vfWriteBack(i).wen && (io.vfWriteBack(i).fpWen || io.vfWriteBack(i).vecWen) 133730cfbc0SXuan Hu wb.bits := io.vfWriteBack(i).addr 134730cfbc0SXuan Hu } 135730cfbc0SXuan Hu case None => 136730cfbc0SXuan Hu } 137730cfbc0SXuan Hu 138730cfbc0SXuan Hu val wakeupFromWBVec = Wire(Vec(params.numWakeupFromWB, ValidIO(new IssueQueueWakeUpBundle(params.pregIdxWidth)))) 139730cfbc0SXuan Hu val writeback = params.schdType match { 140730cfbc0SXuan Hu case IntScheduler() => io.intWriteBack 141730cfbc0SXuan Hu case MemScheduler() => io.intWriteBack ++ io.vfWriteBack 142730cfbc0SXuan Hu case VfScheduler() => io.vfWriteBack 143730cfbc0SXuan Hu case _ => Seq() 144730cfbc0SXuan Hu } 145730cfbc0SXuan Hu wakeupFromWBVec.zip(writeback).foreach { case (sink, source) => 146730cfbc0SXuan Hu sink.valid := source.wen 147730cfbc0SXuan Hu sink.bits.rfWen := source.intWen 148730cfbc0SXuan Hu sink.bits.fpWen := source.fpWen 149730cfbc0SXuan Hu sink.bits.vecWen := source.vecWen 150730cfbc0SXuan Hu sink.bits.pdest := source.addr 151730cfbc0SXuan Hu } 152730cfbc0SXuan Hu 153730cfbc0SXuan Hu io.toDataPath.zipWithIndex.foreach { case (toDp, i) => 154730cfbc0SXuan Hu toDp <> issueQueues(i).io.deq 155730cfbc0SXuan Hu } 156730cfbc0SXuan Hu} 157730cfbc0SXuan Hu 158730cfbc0SXuan Huclass SchedulerArithImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 159730cfbc0SXuan Hu extends SchedulerImpBase(wrapper) 160730cfbc0SXuan Hu with HasXSParameter 161730cfbc0SXuan Hu{ 162730cfbc0SXuan Hu println(s"[SchedulerArithImp] " + 163730cfbc0SXuan Hu s"has intBusyTable: ${intBusyTable.nonEmpty}, " + 164730cfbc0SXuan Hu s"has vfBusyTable: ${vfBusyTable.nonEmpty}") 165730cfbc0SXuan Hu 166730cfbc0SXuan Hu issueQueues.zipWithIndex.foreach { case (iq, i) => 167730cfbc0SXuan Hu iq.io.flush <> io.fromCtrlBlock.flush 168730cfbc0SXuan Hu iq.io.enq <> dispatch2Iq.io.out(i) 169730cfbc0SXuan Hu iq.io.wakeup := wakeupFromWBVec 170730cfbc0SXuan Hu iq.io.deqResp.zipWithIndex.foreach { case (deqResp, j) => 171ea0f92d8Sczw deqResp.valid := iq.io.deq(j).valid && io.toDataPath(i)(j).ready 172730cfbc0SXuan Hu deqResp.bits.success := false.B 173ea0f92d8Sczw deqResp.bits.respType := RSFeedbackType.issueSuccess 174730cfbc0SXuan Hu deqResp.bits.addrOH := iq.io.deq(j).bits.addrOH 175730cfbc0SXuan Hu } 176730cfbc0SXuan Hu iq.io.og0Resp.zipWithIndex.foreach { case (og0Resp, j) => 177730cfbc0SXuan Hu og0Resp.valid := io.fromDataPath(i)(j).og0resp.valid 178730cfbc0SXuan Hu og0Resp.bits.success := false.B // Todo: remove it 179730cfbc0SXuan Hu og0Resp.bits.respType := io.fromDataPath(i)(j).og0resp.bits.respType 180730cfbc0SXuan Hu og0Resp.bits.addrOH := io.fromDataPath(i)(j).og0resp.bits.addrOH 181730cfbc0SXuan Hu } 182730cfbc0SXuan Hu iq.io.og1Resp.zipWithIndex.foreach { case (og1Resp, j) => 183730cfbc0SXuan Hu og1Resp.valid := io.fromDataPath(i)(j).og1resp.valid 184730cfbc0SXuan Hu og1Resp.bits.success := false.B 185730cfbc0SXuan Hu og1Resp.bits.respType := io.fromDataPath(i)(j).og1resp.bits.respType 186730cfbc0SXuan Hu og1Resp.bits.addrOH := io.fromDataPath(i)(j).og1resp.bits.addrOH 187730cfbc0SXuan Hu } 188730cfbc0SXuan Hu } 189730cfbc0SXuan Hu 190730cfbc0SXuan Hu val iqJumpBundleVec: Seq[IssueQueueJumpBundle] = issueQueues.map { 191730cfbc0SXuan Hu case imp: IssueQueueIntImp => imp.io.enqJmp 192730cfbc0SXuan Hu case _ => None 193730cfbc0SXuan Hu }.filter(_.nonEmpty).flatMap(_.get) 194730cfbc0SXuan Hu println(s"[Scheduler] iqJumpBundleVec: ${iqJumpBundleVec}") 195730cfbc0SXuan Hu 196730cfbc0SXuan Hu iqJumpBundleVec.zip(io.fromCtrlBlock.pcVec zip io.fromCtrlBlock.targetVec).foreach { case (iqJmp, (pc, target)) => 197730cfbc0SXuan Hu iqJmp.pc := pc 198730cfbc0SXuan Hu iqJmp.target := target 199730cfbc0SXuan Hu } 200730cfbc0SXuan Hu} 201730cfbc0SXuan Hu 202730cfbc0SXuan Huclass SchedulerMemImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 203730cfbc0SXuan Hu extends SchedulerImpBase(wrapper) 204730cfbc0SXuan Hu with HasXSParameter 205730cfbc0SXuan Hu{ 206730cfbc0SXuan Hu println(s"[SchedulerMemImp] " + 207730cfbc0SXuan Hu s"has intBusyTable: ${intBusyTable.nonEmpty}, " + 208730cfbc0SXuan Hu s"has vfBusyTable: ${vfBusyTable.nonEmpty}") 209730cfbc0SXuan Hu 210730cfbc0SXuan Hu val memAddrIQs = issueQueues.filter(iq => iq.params.StdCnt == 0) 211730cfbc0SXuan Hu val stAddrIQs = issueQueues.filter(iq => iq.params.StaCnt > 0) // included in memAddrIQs 212*7b753bebSXuan Hu val ldAddrIQs = issueQueues.filter(iq => iq.params.LduCnt > 0) 213730cfbc0SXuan Hu val stDataIQs = issueQueues.filter(iq => iq.params.StdCnt > 0) 214730cfbc0SXuan Hu require(memAddrIQs.nonEmpty && stDataIQs.nonEmpty) 215730cfbc0SXuan Hu 216730cfbc0SXuan Hu issueQueues.zipWithIndex.foreach { case (iq, i) => 217730cfbc0SXuan Hu iq.io.deqResp.zipWithIndex.foreach { case (deqResp, j) => 218ea0f92d8Sczw deqResp.valid := iq.io.deq(j).valid && io.toDataPath(i)(j).ready 219730cfbc0SXuan Hu deqResp.bits.success := false.B 220ea0f92d8Sczw deqResp.bits.respType := RSFeedbackType.issueSuccess 221730cfbc0SXuan Hu deqResp.bits.addrOH := iq.io.deq(j).bits.addrOH 222730cfbc0SXuan Hu } 223730cfbc0SXuan Hu iq.io.og0Resp.zipWithIndex.foreach { case (og0Resp, j) => 224730cfbc0SXuan Hu og0Resp.valid := io.fromDataPath(i)(j).og0resp.valid 225730cfbc0SXuan Hu og0Resp.bits.success := false.B // Todo: remove it 226730cfbc0SXuan Hu og0Resp.bits.respType := io.fromDataPath(i)(j).og0resp.bits.respType 227730cfbc0SXuan Hu og0Resp.bits.addrOH := io.fromDataPath(i)(j).og0resp.bits.addrOH 228730cfbc0SXuan Hu } 229730cfbc0SXuan Hu iq.io.og1Resp.zipWithIndex.foreach { case (og1Resp, j) => 230730cfbc0SXuan Hu og1Resp.valid := io.fromDataPath(i)(j).og1resp.valid 231730cfbc0SXuan Hu og1Resp.bits.success := false.B 232730cfbc0SXuan Hu og1Resp.bits.respType := io.fromDataPath(i)(j).og1resp.bits.respType 233730cfbc0SXuan Hu og1Resp.bits.addrOH := io.fromDataPath(i)(j).og1resp.bits.addrOH 234730cfbc0SXuan Hu } 235730cfbc0SXuan Hu } 236730cfbc0SXuan Hu 237730cfbc0SXuan Hu memAddrIQs.zipWithIndex.foreach { case (iq, i) => 238730cfbc0SXuan Hu iq.io.flush <> io.fromCtrlBlock.flush 239730cfbc0SXuan Hu iq.io.enq <> dispatch2Iq.io.out(i) 240730cfbc0SXuan Hu iq.io.wakeup := wakeupFromWBVec 241730cfbc0SXuan Hu } 242730cfbc0SXuan Hu 243*7b753bebSXuan Hu ldAddrIQs.foreach { 244*7b753bebSXuan Hu case imp: IssueQueueMemAddrImp => imp.io.memIO.get.feedbackIO <> io.fromMem.get.ldaFeedback 245*7b753bebSXuan Hu case _ => 246*7b753bebSXuan Hu } 247*7b753bebSXuan Hu 248*7b753bebSXuan Hu stAddrIQs.foreach { 249*7b753bebSXuan Hu case imp: IssueQueueMemAddrImp => imp.io.memIO.get.feedbackIO <> io.fromMem.get.staFeedback 250*7b753bebSXuan Hu case _ => 251*7b753bebSXuan Hu } 252730cfbc0SXuan Hu 253730cfbc0SXuan Hu dispatch2Iq.io.out(1).zip(stAddrIQs(0).io.enq).zip(stDataIQs(0).io.enq).foreach{ case((di, staIQ), stdIQ) => 254730cfbc0SXuan Hu val isAllReady = staIQ.ready && stdIQ.ready 255730cfbc0SXuan Hu di.ready := isAllReady 256730cfbc0SXuan Hu staIQ.valid := di.valid && isAllReady 257730cfbc0SXuan Hu stdIQ.valid := di.valid && isAllReady 258730cfbc0SXuan Hu } 259730cfbc0SXuan Hu 260730cfbc0SXuan Hu require(stAddrIQs.size == stDataIQs.size, s"number of store address IQs(${stAddrIQs.size}) " + 261730cfbc0SXuan Hu s"should be equal to number of data IQs(${stDataIQs})") 262730cfbc0SXuan Hu stDataIQs.zip(stAddrIQs).zipWithIndex.foreach { case ((stdIQ, staIQ), i) => 263730cfbc0SXuan Hu stdIQ.io.flush <> io.fromCtrlBlock.flush 264730cfbc0SXuan Hu 265730cfbc0SXuan Hu stdIQ.io.enq.zip(staIQ.io.enq).foreach { case (stdIQEnq, staIQEnq) => 266730cfbc0SXuan Hu stdIQEnq.bits := staIQEnq.bits 267730cfbc0SXuan Hu // Store data reuses store addr src(1) in dispatch2iq 268730cfbc0SXuan Hu // [dispatch2iq] --src*------src*(0)--> [staIQ] 269730cfbc0SXuan Hu // \ 270730cfbc0SXuan Hu // ---src*(1)--> [stdIQ] 271730cfbc0SXuan Hu // Since the src(1) of sta is easier to get, stdIQEnq.bits.src*(0) is assigned to staIQEnq.bits.src*(1) 272730cfbc0SXuan Hu // instead of dispatch2Iq.io.out(x).bits.src*(1) 273730cfbc0SXuan Hu stdIQEnq.bits.srcState(0) := staIQEnq.bits.srcState(1) 274730cfbc0SXuan Hu stdIQEnq.bits.srcType(0) := staIQEnq.bits.srcType(1) 275730cfbc0SXuan Hu stdIQEnq.bits.psrc(0) := staIQEnq.bits.psrc(1) 276730cfbc0SXuan Hu stdIQEnq.bits.sqIdx := staIQEnq.bits.sqIdx 277730cfbc0SXuan Hu } 278730cfbc0SXuan Hu stdIQ.io.wakeup := wakeupFromWBVec 279730cfbc0SXuan Hu } 280730cfbc0SXuan Hu 281730cfbc0SXuan Hu val lsqEnqCtrl = Module(new LsqEnqCtrl) 282730cfbc0SXuan Hu 283730cfbc0SXuan Hu lsqEnqCtrl.io.redirect <> io.fromCtrlBlock.flush 284730cfbc0SXuan Hu lsqEnqCtrl.io.enq <> dispatch2Iq.io.enqLsqIO.get 285730cfbc0SXuan Hu lsqEnqCtrl.io.lcommit := io.fromMem.get.lcommit 286730cfbc0SXuan Hu lsqEnqCtrl.io.scommit := io.fromMem.get.scommit 287730cfbc0SXuan Hu lsqEnqCtrl.io.lqCancelCnt := io.fromMem.get.lqCancelCnt 288730cfbc0SXuan Hu lsqEnqCtrl.io.sqCancelCnt := io.fromMem.get.sqCancelCnt 289730cfbc0SXuan Hu io.memIO.get.lsqEnqIO <> lsqEnqCtrl.io.enqLsq 290730cfbc0SXuan Hu} 291