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 issueQueues.filter(iq => iq.params.StaCnt > 0).map(_.io.enq).flatten.zipWithIndex.map{ case (iq, idx) => 389 iq.valid := io.fromDispatch.uops(staIdx(idx)).valid && !io.fromDispatch.uops(staIdx(idx)).bits.isDropAmocasSta 390 } 391 val staValidFromDispatch = staIdx.map(idx => io.fromDispatch.uops(idx).valid) 392 val memAddrIQs = issueQueues.filter(_.params.isMemAddrIQ) 393 val stAddrIQs = issueQueues.filter(iq => iq.params.StaCnt > 0) // included in memAddrIQs 394 val ldAddrIQs = issueQueues.filter(iq => iq.params.LduCnt > 0) 395 val stDataIQs = issueQueues.filter(iq => iq.params.StdCnt > 0) 396 val vecMemIQs = issueQueues.filter(_.params.isVecMemIQ) 397 val (hyuIQs, hyuIQIdxs) = issueQueues.zipWithIndex.filter(_._1.params.HyuCnt > 0).unzip 398 399 println(s"[SchedulerMemImp] memAddrIQs.size: ${memAddrIQs.size}, enq.size: ${memAddrIQs.map(_.io.enq.size).sum}") 400 println(s"[SchedulerMemImp] stAddrIQs.size: ${stAddrIQs.size }, enq.size: ${stAddrIQs.map(_.io.enq.size).sum}") 401 println(s"[SchedulerMemImp] ldAddrIQs.size: ${ldAddrIQs.size }, enq.size: ${ldAddrIQs.map(_.io.enq.size).sum}") 402 println(s"[SchedulerMemImp] stDataIQs.size: ${stDataIQs.size }, enq.size: ${stDataIQs.map(_.io.enq.size).sum}") 403 println(s"[SchedulerMemImp] hyuIQs.size: ${hyuIQs.size }, enq.size: ${hyuIQs.map(_.io.enq.size).sum}") 404 require(memAddrIQs.nonEmpty && stDataIQs.nonEmpty) 405 406 io.toMem.get.loadFastMatch := 0.U.asTypeOf(io.toMem.get.loadFastMatch) // TODO: is still needed? 407 408 private val loadWakeUp = issueQueues.filter(_.params.LdExuCnt > 0).map(_.asInstanceOf[IssueQueueMemAddrImp].io.memIO.get.loadWakeUp).flatten 409 require(loadWakeUp.length == io.fromMem.get.wakeup.length) 410 loadWakeUp.zip(io.fromMem.get.wakeup).foreach(x => x._1 := x._2) 411 412 memAddrIQs.zipWithIndex.foreach { case (iq, i) => 413 iq.io.flush <> io.fromCtrlBlock.flush 414 if (!iq.params.needLoadDependency) { 415 iq.io.enq.map(x => x.bits.srcLoadDependency := 0.U.asTypeOf(x.bits.srcLoadDependency)) 416 } 417 iq.io.wakeupFromWB.zip( 418 wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 419 wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 420 wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 421 wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 422 wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1) 423 ).foreach{ case (sink, source) => sink := source} 424 iq.io.wakeupFromWBDelayed.zip( 425 wakeupFromIntWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 426 wakeupFromFpWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 427 wakeupFromVfWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 428 wakeupFromV0WBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 429 wakeupFromVlWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1) 430 ).foreach { case (sink, source) => sink := source } 431 } 432 433 ldAddrIQs.zipWithIndex.foreach { 434 case (imp: IssueQueueMemAddrImp, i) => 435 imp.io.memIO.get.feedbackIO.head := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO.head) 436 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 437 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 438 case _ => 439 } 440 441 stAddrIQs.zipWithIndex.foreach { 442 case (imp: IssueQueueMemAddrImp, i) => 443 imp.io.memIO.get.feedbackIO.head := io.fromMem.get.staFeedback(i) 444 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 445 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 446 case _ => 447 } 448 449 hyuIQs.zip(hyuIQIdxs).foreach { 450 case (imp: IssueQueueMemAddrImp, idx) => 451 imp.io.memIO.get.feedbackIO.head := io.fromMem.get.hyuFeedback.head 452 imp.io.memIO.get.feedbackIO(1) := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO(1)) 453 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 454 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 455 // TODO: refactor ditry code 456 imp.io.deqDelay(1).ready := false.B 457 io.toDataPathAfterDelay(idx)(1).valid := false.B 458 io.toDataPathAfterDelay(idx)(1).bits := 0.U.asTypeOf(io.toDataPathAfterDelay(idx)(1).bits) 459 case _ => 460 } 461 462 private val staIdxSeq = (stAddrIQs).map(iq => iq.params.idxInSchBlk) 463 private val hyaIdxSeq = (hyuIQs).map(iq => iq.params.idxInSchBlk) 464 465 println(s"[SchedulerMemImp] sta iq idx in memSchdBlock: $staIdxSeq") 466 println(s"[SchedulerMemImp] hya iq idx in memSchdBlock: $hyaIdxSeq") 467 468 private val staEnqs = stAddrIQs.map(_.io.enq).flatten 469 private val stdEnqs = stDataIQs.map(_.io.enq).flatten.take(staEnqs.size) 470 private val hyaEnqs = hyuIQs.map(_.io.enq).flatten 471 private val hydEnqs = stDataIQs.map(_.io.enq).flatten.drop(staEnqs.size) 472 473 require(staEnqs.size == stdEnqs.size, s"number of enq ports of store address IQs(${staEnqs.size}) " + 474 s"should be equal to number of enq ports of store data IQs(${stdEnqs.size})") 475 476 require(hyaEnqs.size == hydEnqs.size, s"number of enq ports of hybrid address IQs(${hyaEnqs.size}) " + 477 s"should be equal to number of enq ports of hybrid data IQs(${hydEnqs.size})") 478 479 stDataIQs.zipWithIndex.foreach { case (iq, i) => 480 iq.io.flush <> io.fromCtrlBlock.flush 481 iq.io.wakeupFromWB.zip( 482 wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 483 wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 484 wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 485 wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 486 wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 487 ).foreach{ case (sink, source) => sink := source} 488 iq.io.wakeupFromWBDelayed.zip( 489 wakeupFromIntWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 490 wakeupFromFpWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 491 wakeupFromVfWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 492 wakeupFromV0WBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 493 wakeupFromVlWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 494 ).foreach { case (sink, source) => sink := source } 495 // here disable fp load fast wakeup to std, and no FEX wakeup to std 496 iq.io.wakeupFromIQ.map(_.bits.fpWen := false.B) 497 } 498 499 (stdEnqs ++ hydEnqs).zip(staEnqs ++ hyaEnqs).zipWithIndex.foreach { case ((stdIQEnq, staIQEnq), i) => 500 stdIQEnq.valid := staValidFromDispatch(i) 501 stdIQEnq.bits := staIQEnq.bits 502 // Store data reuses store addr src(1) in dispatch2iq 503 // [dispatch2iq] --src*------src*(0)--> [staIQ|hyaIQ] 504 // \ 505 // ---src*(1)--> [stdIQ] 506 // Since the src(1) of sta is easier to get, stdIQEnq.bits.src*(0) is assigned to staIQEnq.bits.src*(1) 507 // instead of dispatch2Iq.io.out(x).bits.src*(1) 508 val stdIdx = 1 509 stdIQEnq.bits.srcState(0) := staIQEnq.bits.srcState(stdIdx) 510 stdIQEnq.bits.srcLoadDependency(0) := staIQEnq.bits.srcLoadDependency(stdIdx) 511 stdIQEnq.bits.srcType(0) := staIQEnq.bits.srcType(stdIdx) 512 stdIQEnq.bits.psrc(0) := staIQEnq.bits.psrc(stdIdx) 513 stdIQEnq.bits.sqIdx := staIQEnq.bits.sqIdx 514 stdIQEnq.bits.useRegCache(0) := staIQEnq.bits.useRegCache(stdIdx) 515 stdIQEnq.bits.regCacheIdx(0) := staIQEnq.bits.regCacheIdx(stdIdx) 516 } 517 518 vecMemIQs.foreach { 519 case imp: IssueQueueVecMemImp => 520 imp.io.memIO.get.sqDeqPtr.foreach(_ := io.fromMem.get.sqDeqPtr) 521 imp.io.memIO.get.lqDeqPtr.foreach(_ := io.fromMem.get.lqDeqPtr) 522 // not used 523 //imp.io.memIO.get.feedbackIO.head := io.fromMem.get.vstuFeedback.head // only vector store replay 524 // maybe not used 525 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 526 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 527 imp.io.wakeupFromWB.zip( 528 wakeupFromIntWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 529 wakeupFromFpWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 530 wakeupFromVfWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 531 wakeupFromV0WBVec.zipWithIndex.filter(x => imp.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 532 wakeupFromVlWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 533 ).foreach{ case (sink, source) => sink := source} 534 imp.io.wakeupFromWBDelayed.zip( 535 wakeupFromIntWBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 536 wakeupFromFpWBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 537 wakeupFromVfWBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 538 wakeupFromV0WBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 539 wakeupFromVlWBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 540 ).foreach { case (sink, source) => sink := source } 541 542 case _ => 543 } 544 val vecMemFeedbackIO: Seq[MemRSFeedbackIO] = vecMemIQs.map { 545 case imp: IssueQueueVecMemImp => 546 imp.io.memIO.get.feedbackIO 547 }.flatten 548 assert(vecMemFeedbackIO.size == io.fromMem.get.vstuFeedback.size, "vecMemFeedback size dont match!") 549 vecMemFeedbackIO.zip(io.fromMem.get.vstuFeedback).foreach{ 550 case (sink, source) => 551 sink := source 552 } 553 554 val perfEvents = basePerfEvents 555 generatePerfEvent() 556} 557