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.mem.{LsqEnqCtrl, LsqEnqIO, MemWaitUpdateReq, SqPtr, LqPtr} 16import xiangshan.backend.datapath.WbConfig.V0WB 17import xiangshan.backend.regfile.VlPregParams 18import xiangshan.backend.regcache.RegCacheTagTable 19 20sealed trait SchedulerType 21 22case class IntScheduler() extends SchedulerType 23case class FpScheduler() extends SchedulerType 24case class MemScheduler() extends SchedulerType 25case class VfScheduler() extends SchedulerType 26case class NoScheduler() extends SchedulerType 27 28class Scheduler(val params: SchdBlockParams)(implicit p: Parameters) extends LazyModule with HasXSParameter { 29 override def shouldBeInlined: Boolean = false 30 31 val numIntStateWrite = backendParams.numPregWb(IntData()) 32 val numFpStateWrite = backendParams.numPregWb(FpData()) 33 val numVfStateWrite = backendParams.numPregWb(VecData()) 34 val numV0StateWrite = backendParams.numPregWb(V0Data()) 35 val numVlStateWrite = backendParams.numPregWb(VlData()) 36 37 val issueQueue = params.issueBlockParams.map(x => LazyModule(new IssueQueue(x).suggestName(x.getIQName))) 38 39 lazy val module: SchedulerImpBase = params.schdType match { 40 case IntScheduler() => new SchedulerArithImp(this)(params, p) 41 case FpScheduler() => new SchedulerArithImp(this)(params, p) 42 case MemScheduler() => new SchedulerMemImp(this)(params, p) 43 case VfScheduler() => new SchedulerArithImp(this)(params, p) 44 case _ => null 45 } 46} 47 48class SchedulerIO()(implicit params: SchdBlockParams, p: Parameters) extends XSBundle { 49 // params alias 50 private val LoadQueueSize = VirtualLoadQueueSize 51 val fromDispatchUopNum = params.issueBlockParams.filter(x => x.StdCnt == 0).map(_.numEnq).sum 52 val allIssueParams = params.issueBlockParams.filter(_.StdCnt == 0) 53 val IssueQueueDeqSum = allIssueParams.map(_.numDeq).sum 54 val maxIQSize = allIssueParams.map(_.numEntries).max 55 val fromTop = new Bundle { 56 val hartId = Input(UInt(8.W)) 57 } 58 val fromWbFuBusyTable = new Bundle{ 59 val fuBusyTableRead = MixedVec(params.issueBlockParams.map(x => Input(x.genWbFuBusyTableReadBundle))) 60 } 61 val wbFuBusyTable = MixedVec(params.issueBlockParams.map(x => Output(x.genWbFuBusyTableWriteBundle))) 62 val IQValidNumVec = Output(Vec(IssueQueueDeqSum, UInt((maxIQSize).U.getWidth.W))) 63 64 val fromCtrlBlock = new Bundle { 65 val flush = Flipped(ValidIO(new Redirect)) 66 } 67 val fromDispatch = new Bundle { 68 val uops = Vec(fromDispatchUopNum, Flipped(DecoupledIO(new DynInst))) 69 } 70 val intWriteBack = MixedVec(Vec(backendParams.numPregWb(IntData()), 71 new RfWritePortWithConfig(backendParams.intPregParams.dataCfg, backendParams.intPregParams.addrWidth))) 72 val fpWriteBack = MixedVec(Vec(backendParams.numPregWb(FpData()), 73 new RfWritePortWithConfig(backendParams.fpPregParams.dataCfg, backendParams.fpPregParams.addrWidth))) 74 val vfWriteBack = MixedVec(Vec(backendParams.numPregWb(VecData()), 75 new RfWritePortWithConfig(backendParams.vfPregParams.dataCfg, backendParams.vfPregParams.addrWidth))) 76 val v0WriteBack = MixedVec(Vec(backendParams.numPregWb(V0Data()), 77 new RfWritePortWithConfig(backendParams.v0PregParams.dataCfg, backendParams.v0PregParams.addrWidth))) 78 val vlWriteBack = MixedVec(Vec(backendParams.numPregWb(VlData()), 79 new RfWritePortWithConfig(backendParams.vlPregParams.dataCfg, backendParams.vlPregParams.addrWidth))) 80 val intWriteBackDelayed = MixedVec(Vec(backendParams.numPregWb(IntData()), 81 new RfWritePortWithConfig(backendParams.intPregParams.dataCfg, backendParams.intPregParams.addrWidth))) 82 val fpWriteBackDelayed = MixedVec(Vec(backendParams.numPregWb(FpData()), 83 new RfWritePortWithConfig(backendParams.fpPregParams.dataCfg, backendParams.fpPregParams.addrWidth))) 84 val vfWriteBackDelayed = MixedVec(Vec(backendParams.numPregWb(VecData()), 85 new RfWritePortWithConfig(backendParams.vfPregParams.dataCfg, backendParams.vfPregParams.addrWidth))) 86 val v0WriteBackDelayed = MixedVec(Vec(backendParams.numPregWb(V0Data()), 87 new RfWritePortWithConfig(backendParams.v0PregParams.dataCfg, backendParams.v0PregParams.addrWidth))) 88 val vlWriteBackDelayed = MixedVec(Vec(backendParams.numPregWb(VlData()), 89 new RfWritePortWithConfig(backendParams.vlPregParams.dataCfg, backendParams.vlPregParams.addrWidth))) 90 val toDataPathAfterDelay: MixedVec[MixedVec[DecoupledIO[IssueQueueIssueBundle]]] = MixedVec(params.issueBlockParams.map(_.genIssueDecoupledBundle)) 91 92 val vlWriteBackInfo = new Bundle { 93 val vlFromIntIsZero = Input(Bool()) 94 val vlFromIntIsVlmax = Input(Bool()) 95 val vlFromVfIsZero = Input(Bool()) 96 val vlFromVfIsVlmax = Input(Bool()) 97 } 98 99 val fromSchedulers = new Bundle { 100 val wakeupVec: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpInValidBundle) 101 val wakeupVecDelayed: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpInValidBundle) 102 } 103 104 val toSchedulers = new Bundle { 105 val wakeupVec: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = params.genIQWakeUpOutValidBundle 106 } 107 108 val fromDataPath = new Bundle { 109 val resp: MixedVec[MixedVec[OGRespBundle]] = MixedVec(params.issueBlockParams.map(x => Flipped(x.genOGRespBundle))) 110 val og0Cancel = Input(ExuVec()) 111 // Todo: remove this after no cancel signal from og1 112 val og1Cancel = Input(ExuVec()) 113 // replace RCIdx to Wakeup Queue 114 val replaceRCIdx = OptionWrapper(params.needWriteRegCache, Vec(params.numWriteRegCache, Input(UInt(RegCacheIdxWidth.W)))) 115 // just be compatible to old code 116 def apply(i: Int)(j: Int) = resp(i)(j) 117 } 118 119 val loadFinalIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.LdExuCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x))))))) 120 val vecLoadFinalIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.VlduCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x))))))) 121 val memAddrIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.LdExuCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x))))))) 122 val vecLoadIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.VlduCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x))))))) 123 124 val ldCancel = Vec(backendParams.LduCnt + backendParams.HyuCnt, Flipped(new LoadCancelIO)) 125 126 val fromMem = if (params.isMemSchd) Some(new Bundle { 127 val ldaFeedback = Flipped(Vec(params.LduCnt, new MemRSFeedbackIO)) 128 val staFeedback = Flipped(Vec(params.StaCnt, new MemRSFeedbackIO)) 129 val hyuFeedback = Flipped(Vec(params.HyuCnt, new MemRSFeedbackIO)) 130 val vstuFeedback = Flipped(Vec(params.VstuCnt, new MemRSFeedbackIO(isVector = true))) 131 val vlduFeedback = Flipped(Vec(params.VlduCnt, new MemRSFeedbackIO(isVector = true))) 132 val stIssuePtr = Input(new SqPtr()) 133 val lcommit = Input(UInt(log2Up(CommitWidth + 1).W)) 134 val scommit = Input(UInt(log2Ceil(EnsbufferWidth + 1).W)) // connected to `memBlock.io.sqDeq` instead of ROB 135 val wakeup = Vec(params.LdExuCnt, Flipped(Valid(new DynInst))) 136 val lqDeqPtr = Input(new LqPtr) 137 val sqDeqPtr = Input(new SqPtr) 138 // from lsq 139 val lqCancelCnt = Input(UInt(log2Up(LoadQueueSize + 1).W)) 140 val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W)) 141 val memWaitUpdateReq = Flipped(new MemWaitUpdateReq) 142 }) else None 143 val toMem = if (params.isMemSchd) Some(new Bundle { 144 val loadFastMatch = Output(Vec(params.LduCnt, new IssueQueueLoadBundle)) 145 }) else None 146 val fromOg2Resp = if(params.needOg2Resp) Some(MixedVec(params.issueBlockParams.filter(_.needOg2Resp).map(x => Flipped(x.genOG2RespBundle)))) else None 147} 148 149abstract class SchedulerImpBase(wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 150 extends LazyModuleImp(wrapper) 151 with HasXSParameter 152{ 153 val io = IO(new SchedulerIO()) 154 155 // alias 156 private val iqWakeUpInMap: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] = 157 io.fromSchedulers.wakeupVec.map(x => (x.bits.exuIdx, x)).toMap 158 private val iqWakeUpInMapDelayed: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] = 159 io.fromSchedulers.wakeupVecDelayed.map(x => (x.bits.exuIdx, x)).toMap 160 private val schdType = params.schdType 161 162 // Modules 163 val issueQueues: Seq[IssueQueueImp] = wrapper.issueQueue.map(_.module) 164 165 io.IQValidNumVec := issueQueues.filter(_.params.StdCnt == 0).map(_.io.validCntDeqVec).flatten 166 val wakeupFromIntWBVec = Wire(params.genIntWBWakeUpSinkValidBundle) 167 val wakeupFromFpWBVec = Wire(params.genFpWBWakeUpSinkValidBundle) 168 val wakeupFromVfWBVec = Wire(params.genVfWBWakeUpSinkValidBundle) 169 val wakeupFromV0WBVec = Wire(params.genV0WBWakeUpSinkValidBundle) 170 val wakeupFromVlWBVec = Wire(params.genVlWBWakeUpSinkValidBundle) 171 val wakeupFromIntWBVecDelayed = Wire(params.genIntWBWakeUpSinkValidBundle) 172 val wakeupFromFpWBVecDelayed = Wire(params.genFpWBWakeUpSinkValidBundle) 173 val wakeupFromVfWBVecDelayed = Wire(params.genVfWBWakeUpSinkValidBundle) 174 val wakeupFromV0WBVecDelayed = Wire(params.genV0WBWakeUpSinkValidBundle) 175 val wakeupFromVlWBVecDelayed = Wire(params.genVlWBWakeUpSinkValidBundle) 176 177 val wakeupFromWBVec = Seq(wakeupFromIntWBVec, wakeupFromFpWBVec, wakeupFromVfWBVec, wakeupFromV0WBVec, wakeupFromVlWBVec) 178 val allWriteBack = Seq(io.intWriteBack, io.fpWriteBack, io.vfWriteBack, io.v0WriteBack, io.vlWriteBack) 179 wakeupFromWBVec.zip(allWriteBack).map{ case (sinks, sources) => 180 sinks.zip(sources).map{ case (sink, source) => 181 sink.valid := source.wen 182 sink.bits.rfWen := source.intWen 183 sink.bits.fpWen := source.fpWen 184 sink.bits.vecWen := source.vecWen 185 sink.bits.v0Wen := source.v0Wen 186 sink.bits.vlWen := source.vlWen 187 sink.bits.pdest := source.addr 188 } 189 } 190 191 val wakeupFromWBVecDelayed = Seq(wakeupFromIntWBVecDelayed, wakeupFromFpWBVecDelayed, wakeupFromVfWBVecDelayed, wakeupFromV0WBVecDelayed, wakeupFromVlWBVecDelayed) 192 val allWriteBackDelayed = Seq(io.intWriteBackDelayed, io.fpWriteBackDelayed, io.vfWriteBackDelayed, io.v0WriteBackDelayed, io.vlWriteBackDelayed) 193 wakeupFromWBVecDelayed.zip(allWriteBackDelayed).map { case (sinks, sources) => 194 sinks.zip(sources).map { case (sink, source) => 195 sink.valid := source.wen 196 sink.bits.rfWen := source.intWen 197 sink.bits.fpWen := source.fpWen 198 sink.bits.vecWen := source.vecWen 199 sink.bits.v0Wen := source.v0Wen 200 sink.bits.vlWen := source.vlWen 201 sink.bits.pdest := source.addr 202 } 203 } 204 // Connect bundles having the same wakeup source 205 issueQueues.zipWithIndex.foreach { case(iq, i) => 206 iq.io.wakeupFromIQ.foreach { wakeUp => 207 val wakeUpIn = iqWakeUpInMap(wakeUp.bits.exuIdx) 208 val exuIdx = wakeUp.bits.exuIdx 209 println(s"[Backend] Connect wakeup exuIdx ${exuIdx}") 210 connectSamePort(wakeUp,wakeUpIn) 211 backendParams.connectWakeup(exuIdx) 212 if (backendParams.isCopyPdest(exuIdx)) { 213 println(s"[Backend] exuIdx ${exuIdx} use pdestCopy ${backendParams.getCopyPdestIndex(exuIdx)}") 214 wakeUp.bits.pdest := wakeUpIn.bits.pdestCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 215 if (wakeUpIn.bits.rfWenCopy.nonEmpty) wakeUp.bits.rfWen := wakeUpIn.bits.rfWenCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 216 if (wakeUpIn.bits.fpWenCopy.nonEmpty) wakeUp.bits.fpWen := wakeUpIn.bits.fpWenCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 217 if (wakeUpIn.bits.vecWenCopy.nonEmpty) wakeUp.bits.vecWen := wakeUpIn.bits.vecWenCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 218 if (wakeUpIn.bits.v0WenCopy.nonEmpty) wakeUp.bits.v0Wen := wakeUpIn.bits.v0WenCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 219 if (wakeUpIn.bits.vlWenCopy.nonEmpty) wakeUp.bits.vlWen := wakeUpIn.bits.vlWenCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 220 if (wakeUpIn.bits.loadDependencyCopy.nonEmpty) wakeUp.bits.loadDependency := wakeUpIn.bits.loadDependencyCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 221 } 222 if (iq.params.numIntSrc == 0) wakeUp.bits.rfWen := false.B 223 if (iq.params.numFpSrc == 0) wakeUp.bits.fpWen := false.B 224 if (iq.params.numVfSrc == 0) wakeUp.bits.vecWen := false.B 225 if (iq.params.numV0Src == 0) wakeUp.bits.v0Wen := false.B 226 if (iq.params.numVlSrc == 0) wakeUp.bits.vlWen := false.B 227 } 228 iq.io.wakeupFromIQDelayed.foreach { wakeUp => 229 val wakeUpIn = iqWakeUpInMapDelayed(wakeUp.bits.exuIdx) 230 connectSamePort(wakeUp, wakeUpIn) 231 if (iq.params.numIntSrc == 0) wakeUp.bits.rfWen := false.B 232 if (iq.params.numFpSrc == 0) wakeUp.bits.fpWen := false.B 233 if (iq.params.numVfSrc == 0) wakeUp.bits.vecWen := false.B 234 if (iq.params.numV0Src == 0) wakeUp.bits.v0Wen := false.B 235 if (iq.params.numVlSrc == 0) wakeUp.bits.vlWen := false.B 236 } 237 iq.io.og0Cancel := io.fromDataPath.og0Cancel 238 iq.io.og1Cancel := io.fromDataPath.og1Cancel 239 if (iq.params.needLoadDependency) 240 iq.io.ldCancel := io.ldCancel 241 else 242 iq.io.ldCancel := 0.U.asTypeOf(io.ldCancel) 243 } 244 245 // connect the vl writeback informatino to the issue queues 246 issueQueues.zipWithIndex.foreach { case(iq, i) => 247 iq.io.vlFromIntIsVlmax := io.vlWriteBackInfo.vlFromIntIsVlmax 248 iq.io.vlFromIntIsZero := io.vlWriteBackInfo.vlFromIntIsZero 249 iq.io.vlFromVfIsVlmax := io.vlWriteBackInfo.vlFromVfIsVlmax 250 iq.io.vlFromVfIsZero := io.vlWriteBackInfo.vlFromVfIsZero 251 } 252 253 private val iqWakeUpOutMap: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] = 254 issueQueues.flatMap(_.io.wakeupToIQ) 255 .map(x => (x.bits.exuIdx, x)) 256 .toMap 257 258 // Connect bundles having the same wakeup source 259 io.toSchedulers.wakeupVec.foreach { wakeUp => 260 wakeUp := iqWakeUpOutMap(wakeUp.bits.exuIdx) 261 } 262 263 io.toDataPathAfterDelay.zipWithIndex.foreach { case (toDpDy, i) => 264 toDpDy <> issueQueues(i).io.deqDelay 265 } 266 267 // Response 268 issueQueues.zipWithIndex.foreach { case (iq, i) => 269 iq.io.og0Resp.zipWithIndex.foreach { case (og0Resp, j) => 270 og0Resp := io.fromDataPath(i)(j).og0resp 271 } 272 iq.io.og1Resp.zipWithIndex.foreach { case (og1Resp, j) => 273 og1Resp := io.fromDataPath(i)(j).og1resp 274 } 275 iq.io.finalIssueResp.foreach(_.zipWithIndex.foreach { case (finalIssueResp, j) => 276 if (io.loadFinalIssueResp(i).isDefinedAt(j) && iq.params.isLdAddrIQ) { 277 finalIssueResp := io.loadFinalIssueResp(i)(j) 278 } else if (io.vecLoadFinalIssueResp(i).isDefinedAt(j) && iq.params.isVecLduIQ) { 279 finalIssueResp := io.vecLoadFinalIssueResp(i)(j) 280 } 281 else { 282 finalIssueResp := 0.U.asTypeOf(finalIssueResp) 283 } 284 }) 285 iq.io.memAddrIssueResp.foreach(_.zipWithIndex.foreach { case (memAddrIssueResp, j) => 286 if (io.memAddrIssueResp(i).isDefinedAt(j)) { 287 memAddrIssueResp := io.memAddrIssueResp(i)(j) 288 } else { 289 memAddrIssueResp := 0.U.asTypeOf(memAddrIssueResp) 290 } 291 }) 292 iq.io.vecLoadIssueResp.foreach(_.zipWithIndex.foreach { case (resp, deqIdx) => 293 resp := io.vecLoadIssueResp(i)(deqIdx) 294 }) 295 iq.io.wbBusyTableRead := io.fromWbFuBusyTable.fuBusyTableRead(i) 296 io.wbFuBusyTable(i) := iq.io.wbBusyTableWrite 297 iq.io.replaceRCIdx.foreach(x => x := 0.U.asTypeOf(x)) 298 } 299 if (params.needOg2Resp) { 300 issueQueues.filter(_.params.needOg2Resp).zip(io.fromOg2Resp.get).foreach{ case (iq, og2RespVec) => 301 iq.io.og2Resp.get.zip(og2RespVec).foreach{ case (iqOg2Resp, og2Resp) => 302 iqOg2Resp := og2Resp 303 } 304 } 305 } 306 307 // Connect each replace RCIdx to IQ 308 if (params.needWriteRegCache) { 309 val iqReplaceRCIdxVec = issueQueues.filter(_.params.needWriteRegCache).flatMap{ iq => 310 iq.params.allExuParams.zip(iq.io.replaceRCIdx.get).filter(_._1.needWriteRegCache).map(_._2) 311 } 312 iqReplaceRCIdxVec.zip(io.fromDataPath.replaceRCIdx.get).foreach{ case (iq, in) => 313 iq := in 314 } 315 316 println(s"[Scheduler] numWriteRegCache: ${params.numWriteRegCache}") 317 println(s"[Scheduler] iqReplaceRCIdxVec: ${iqReplaceRCIdxVec.size}") 318 } 319 320 // perfEvent 321 val lastCycleIqEnqFireVec = RegNext(VecInit(issueQueues.map(_.io.enq.map(_.fire)).flatten)) 322 val lastCycleIqFullVec = RegNext(VecInit(issueQueues.map(_.io.enq.head.ready))) 323 324 val issueQueueFullVecPerf = issueQueues.zip(lastCycleIqFullVec)map{ case (iq, full) => (iq.params.getIQName + s"_full", full) } 325 val basePerfEvents = Seq( 326 ("issueQueue_enq_fire_cnt", PopCount(lastCycleIqEnqFireVec) ) 327 ) ++ issueQueueFullVecPerf 328 329 println(s"[Scheduler] io.fromSchedulers.wakeupVec: ${io.fromSchedulers.wakeupVec.map(x => backendParams.getExuName(x.bits.exuIdx))}") 330 println(s"[Scheduler] iqWakeUpInKeys: ${iqWakeUpInMap.keys}") 331 332 println(s"[Scheduler] iqWakeUpOutKeys: ${iqWakeUpOutMap.keys}") 333 println(s"[Scheduler] io.toSchedulers.wakeupVec: ${io.toSchedulers.wakeupVec.map(x => backendParams.getExuName(x.bits.exuIdx))}") 334} 335 336class SchedulerArithImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 337 extends SchedulerImpBase(wrapper) 338 with HasXSParameter 339 with HasPerfEvents 340{ 341 val issueQueuesUopIn = issueQueues.map(_.io.enq).flatten 342 issueQueuesUopIn.zip(io.fromDispatch.uops).map(x => x._1 <> x._2) 343 issueQueues.zipWithIndex.foreach { case (iq, i) => 344 iq.io.flush <> io.fromCtrlBlock.flush 345 if (!iq.params.needLoadDependency) { 346 iq.io.enq.map(x => x.bits.srcLoadDependency := 0.U.asTypeOf(x.bits.srcLoadDependency)) 347 } 348 val intWBIQ = params.schdType match { 349 case IntScheduler() => wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) 350 case FpScheduler() => wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) 351 case VfScheduler() => (wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 352 wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 353 wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1)) 354 case _ => null 355 } 356 val intWBIQDelayed = params.schdType match { 357 case IntScheduler() => wakeupFromIntWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) 358 case FpScheduler() => wakeupFromFpWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) 359 case VfScheduler() => (wakeupFromVfWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 360 wakeupFromV0WBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 361 wakeupFromVlWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1)) 362 case _ => null 363 } 364 iq.io.wakeupFromWB.zip(intWBIQ).foreach{ case (sink, source) => sink := source} 365 iq.io.wakeupFromWBDelayed.zip(intWBIQDelayed).foreach{ case (sink, source) => sink := source} 366 } 367 368 val perfEvents = basePerfEvents 369 generatePerfEvent() 370} 371 372// FIXME: Vector mem instructions may not be handled properly! 373class SchedulerMemImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 374 extends SchedulerImpBase(wrapper) 375 with HasXSParameter 376 with HasPerfEvents 377{ 378 379 val issueQueuesUopIn = issueQueues.filter(_.params.StdCnt == 0).map(_.io.enq).flatten 380 issueQueuesUopIn.zip(io.fromDispatch.uops).map(x => x._1 <> x._2) 381 val noStdExuParams = params.issueBlockParams.map(x => Seq.fill(x.numEnq)(x.exuBlockParams)).flatten.filter{x => x.map(!_.hasStdFu).reduce(_ && _)} 382 val staIdx = noStdExuParams.zipWithIndex.filter{x => x._1.map(_.hasStoreAddrFu).reduce(_ || _)}.map(_._2) 383 val staReady = issueQueues.filter(iq => iq.params.StaCnt > 0).map(_.io.enq.map(_.ready)).flatten 384 val stdReady = issueQueues.filter(iq => iq.params.StdCnt > 0).map(_.io.enq.map(_.ready)).flatten 385 staIdx.zipWithIndex.map{ case (sta, i) => { 386 io.fromDispatch.uops(sta).ready := staReady(i) && stdReady(i) 387 }} 388 val memAddrIQs = issueQueues.filter(_.params.isMemAddrIQ) 389 val stAddrIQs = issueQueues.filter(iq => iq.params.StaCnt > 0) // included in memAddrIQs 390 val ldAddrIQs = issueQueues.filter(iq => iq.params.LduCnt > 0) 391 val stDataIQs = issueQueues.filter(iq => iq.params.StdCnt > 0) 392 val vecMemIQs = issueQueues.filter(_.params.isVecMemIQ) 393 val (hyuIQs, hyuIQIdxs) = issueQueues.zipWithIndex.filter(_._1.params.HyuCnt > 0).unzip 394 395 println(s"[SchedulerMemImp] memAddrIQs.size: ${memAddrIQs.size}, enq.size: ${memAddrIQs.map(_.io.enq.size).sum}") 396 println(s"[SchedulerMemImp] stAddrIQs.size: ${stAddrIQs.size }, enq.size: ${stAddrIQs.map(_.io.enq.size).sum}") 397 println(s"[SchedulerMemImp] ldAddrIQs.size: ${ldAddrIQs.size }, enq.size: ${ldAddrIQs.map(_.io.enq.size).sum}") 398 println(s"[SchedulerMemImp] stDataIQs.size: ${stDataIQs.size }, enq.size: ${stDataIQs.map(_.io.enq.size).sum}") 399 println(s"[SchedulerMemImp] hyuIQs.size: ${hyuIQs.size }, enq.size: ${hyuIQs.map(_.io.enq.size).sum}") 400 require(memAddrIQs.nonEmpty && stDataIQs.nonEmpty) 401 402 io.toMem.get.loadFastMatch := 0.U.asTypeOf(io.toMem.get.loadFastMatch) // TODO: is still needed? 403 404 private val loadWakeUp = issueQueues.filter(_.params.LdExuCnt > 0).map(_.asInstanceOf[IssueQueueMemAddrImp].io.memIO.get.loadWakeUp).flatten 405 require(loadWakeUp.length == io.fromMem.get.wakeup.length) 406 loadWakeUp.zip(io.fromMem.get.wakeup).foreach(x => x._1 := x._2) 407 408 memAddrIQs.zipWithIndex.foreach { case (iq, i) => 409 iq.io.flush <> io.fromCtrlBlock.flush 410 if (!iq.params.needLoadDependency) { 411 iq.io.enq.map(x => x.bits.srcLoadDependency := 0.U.asTypeOf(x.bits.srcLoadDependency)) 412 } 413 iq.io.wakeupFromWB.zip( 414 wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 415 wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 416 wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 417 wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 418 wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1) 419 ).foreach{ case (sink, source) => sink := source} 420 iq.io.wakeupFromWBDelayed.zip( 421 wakeupFromIntWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 422 wakeupFromFpWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 423 wakeupFromVfWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 424 wakeupFromV0WBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 425 wakeupFromVlWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1) 426 ).foreach { case (sink, source) => sink := source } 427 } 428 429 ldAddrIQs.zipWithIndex.foreach { 430 case (imp: IssueQueueMemAddrImp, i) => 431 imp.io.memIO.get.feedbackIO.head := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO.head) 432 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 433 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 434 case _ => 435 } 436 437 stAddrIQs.zipWithIndex.foreach { 438 case (imp: IssueQueueMemAddrImp, i) => 439 imp.io.memIO.get.feedbackIO.head := io.fromMem.get.staFeedback(i) 440 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 441 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 442 case _ => 443 } 444 445 hyuIQs.zip(hyuIQIdxs).foreach { 446 case (imp: IssueQueueMemAddrImp, idx) => 447 imp.io.memIO.get.feedbackIO.head := io.fromMem.get.hyuFeedback.head 448 imp.io.memIO.get.feedbackIO(1) := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO(1)) 449 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 450 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 451 // TODO: refactor ditry code 452 imp.io.deqDelay(1).ready := false.B 453 io.toDataPathAfterDelay(idx)(1).valid := false.B 454 io.toDataPathAfterDelay(idx)(1).bits := 0.U.asTypeOf(io.toDataPathAfterDelay(idx)(1).bits) 455 case _ => 456 } 457 458 private val staIdxSeq = (stAddrIQs).map(iq => iq.params.idxInSchBlk) 459 private val hyaIdxSeq = (hyuIQs).map(iq => iq.params.idxInSchBlk) 460 461 println(s"[SchedulerMemImp] sta iq idx in memSchdBlock: $staIdxSeq") 462 println(s"[SchedulerMemImp] hya iq idx in memSchdBlock: $hyaIdxSeq") 463 464 private val staEnqs = stAddrIQs.map(_.io.enq).flatten 465 private val stdEnqs = stDataIQs.map(_.io.enq).flatten.take(staEnqs.size) 466 private val hyaEnqs = hyuIQs.map(_.io.enq).flatten 467 private val hydEnqs = stDataIQs.map(_.io.enq).flatten.drop(staEnqs.size) 468 469 require(staEnqs.size == stdEnqs.size, s"number of enq ports of store address IQs(${staEnqs.size}) " + 470 s"should be equal to number of enq ports of store data IQs(${stdEnqs.size})") 471 472 require(hyaEnqs.size == hydEnqs.size, s"number of enq ports of hybrid address IQs(${hyaEnqs.size}) " + 473 s"should be equal to number of enq ports of hybrid data IQs(${hydEnqs.size})") 474 475 stDataIQs.zipWithIndex.foreach { case (iq, i) => 476 iq.io.flush <> io.fromCtrlBlock.flush 477 iq.io.wakeupFromWB.zip( 478 wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 479 wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 480 wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 481 wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 482 wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 483 ).foreach{ case (sink, source) => sink := source} 484 iq.io.wakeupFromWBDelayed.zip( 485 wakeupFromIntWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 486 wakeupFromFpWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 487 wakeupFromVfWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 488 wakeupFromV0WBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 489 wakeupFromVlWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 490 ).foreach { case (sink, source) => sink := source } 491 // here disable fp load fast wakeup to std, and no FEX wakeup to std 492 iq.io.wakeupFromIQ.map(_.bits.fpWen := false.B) 493 } 494 495 (stdEnqs ++ hydEnqs).zip(staEnqs ++ hyaEnqs).zipWithIndex.foreach { case ((stdIQEnq, staIQEnq), i) => 496 stdIQEnq.valid := staIQEnq.valid && FuType.FuTypeOrR(staIQEnq.bits.fuType, FuType.stu, FuType.mou) 497 stdIQEnq.bits := staIQEnq.bits 498 // Store data reuses store addr src(1) in dispatch2iq 499 // [dispatch2iq] --src*------src*(0)--> [staIQ|hyaIQ] 500 // \ 501 // ---src*(1)--> [stdIQ] 502 // Since the src(1) of sta is easier to get, stdIQEnq.bits.src*(0) is assigned to staIQEnq.bits.src*(1) 503 // instead of dispatch2Iq.io.out(x).bits.src*(1) 504 val stdIdx = 1 505 stdIQEnq.bits.srcState(0) := staIQEnq.bits.srcState(stdIdx) 506 stdIQEnq.bits.srcLoadDependency(0) := staIQEnq.bits.srcLoadDependency(stdIdx) 507 stdIQEnq.bits.srcType(0) := staIQEnq.bits.srcType(stdIdx) 508 stdIQEnq.bits.psrc(0) := staIQEnq.bits.psrc(stdIdx) 509 stdIQEnq.bits.sqIdx := staIQEnq.bits.sqIdx 510 stdIQEnq.bits.useRegCache(0) := staIQEnq.bits.useRegCache(stdIdx) 511 stdIQEnq.bits.regCacheIdx(0) := staIQEnq.bits.regCacheIdx(stdIdx) 512 } 513 514 vecMemIQs.foreach { 515 case imp: IssueQueueVecMemImp => 516 imp.io.memIO.get.sqDeqPtr.foreach(_ := io.fromMem.get.sqDeqPtr) 517 imp.io.memIO.get.lqDeqPtr.foreach(_ := io.fromMem.get.lqDeqPtr) 518 // not used 519 //imp.io.memIO.get.feedbackIO.head := io.fromMem.get.vstuFeedback.head // only vector store replay 520 // maybe not used 521 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 522 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 523 imp.io.wakeupFromWB.zip( 524 wakeupFromIntWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 525 wakeupFromFpWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 526 wakeupFromVfWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 527 wakeupFromV0WBVec.zipWithIndex.filter(x => imp.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 528 wakeupFromVlWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 529 ).foreach{ case (sink, source) => sink := source} 530 imp.io.wakeupFromWBDelayed.zip( 531 wakeupFromIntWBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 532 wakeupFromFpWBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 533 wakeupFromVfWBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 534 wakeupFromV0WBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 535 wakeupFromVlWBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 536 ).foreach { case (sink, source) => sink := source } 537 538 case _ => 539 } 540 val vecMemFeedbackIO: Seq[MemRSFeedbackIO] = vecMemIQs.map { 541 case imp: IssueQueueVecMemImp => 542 imp.io.memIO.get.feedbackIO 543 }.flatten 544 assert(vecMemFeedbackIO.size == io.fromMem.get.vstuFeedback.size, "vecMemFeedback size dont match!") 545 vecMemFeedbackIO.zip(io.fromMem.get.vstuFeedback).foreach{ 546 case (sink, source) => 547 sink := source 548 } 549 550 val perfEvents = basePerfEvents 551 generatePerfEvent() 552} 553