1package xiangshan.backend.issue 2 3import org.chipsalliance.cde.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 7import utils.OptionWrapper 8import xiangshan._ 9import xiangshan.backend.Bundles._ 10import xiangshan.backend.datapath.DataConfig.{IntData, VAddrData, VecData, FpData} 11import xiangshan.backend.datapath.WbConfig.{IntWB, FpWB, VfWB} 12import xiangshan.backend.fu.FuType 13import xiangshan.backend.regfile.RfWritePortWithConfig 14import xiangshan.backend.rename.BusyTable 15import xiangshan.mem.{LsqEnqCtrl, LsqEnqIO, MemWaitUpdateReq, SqPtr, LqPtr} 16 17sealed trait SchedulerType 18 19case class IntScheduler() extends SchedulerType 20case class FpScheduler() extends SchedulerType 21case class MemScheduler() extends SchedulerType 22case class VfScheduler() extends SchedulerType 23case class NoScheduler() extends SchedulerType 24 25class Scheduler(val params: SchdBlockParams)(implicit p: Parameters) extends LazyModule with HasXSParameter { 26 override def shouldBeInlined: Boolean = false 27 28 val numIntStateWrite = backendParams.numPregWb(IntData()) 29 val numFpStateWrite = backendParams.numPregWb(FpData()) 30 val numVfStateWrite = backendParams.numPregWb(VecData()) 31 32 val dispatch2Iq = LazyModule(new Dispatch2Iq(params)) 33 val issueQueue = params.issueBlockParams.map(x => LazyModule(new IssueQueue(x).suggestName(x.getIQName))) 34 35 lazy val module: SchedulerImpBase = params.schdType match { 36 case IntScheduler() => new SchedulerArithImp(this)(params, p) 37 case FpScheduler() => new SchedulerArithImp(this)(params, p) 38 case MemScheduler() => new SchedulerMemImp(this)(params, p) 39 case VfScheduler() => new SchedulerArithImp(this)(params, p) 40 case _ => null 41 } 42} 43 44class SchedulerIO()(implicit params: SchdBlockParams, p: Parameters) extends XSBundle { 45 // params alias 46 private val LoadQueueSize = VirtualLoadQueueSize 47 48 val fromTop = new Bundle { 49 val hartId = Input(UInt(8.W)) 50 } 51 val fromWbFuBusyTable = new Bundle{ 52 val fuBusyTableRead = MixedVec(params.issueBlockParams.map(x => Input(x.genWbFuBusyTableReadBundle))) 53 } 54 val wbFuBusyTable = MixedVec(params.issueBlockParams.map(x => Output(x.genWbFuBusyTableWriteBundle))) 55 val intIQValidNumVec = Output(MixedVec(backendParams.genIntIQValidNumBundle)) 56 val fpIQValidNumVec = Output(MixedVec(backendParams.genFpIQValidNumBundle)) 57 58 val fromCtrlBlock = new Bundle { 59 val flush = Flipped(ValidIO(new Redirect)) 60 } 61 val fromDispatch = new Bundle { 62 val allocPregs = Vec(RenameWidth, Input(new ResetPregStateReq)) 63 val uops = Vec(params.numUopIn, Flipped(DecoupledIO(new DynInst))) 64 } 65 val intWriteBack = MixedVec(Vec(backendParams.numPregWb(IntData()), 66 new RfWritePortWithConfig(backendParams.intPregParams.dataCfg, backendParams.intPregParams.addrWidth))) 67 val fpWriteBack = MixedVec(Vec(backendParams.numPregWb(FpData()), 68 new RfWritePortWithConfig(backendParams.fpPregParams.dataCfg, backendParams.fpPregParams.addrWidth))) 69 val vfWriteBack = MixedVec(Vec(backendParams.numPregWb(VecData()), 70 new RfWritePortWithConfig(backendParams.vfPregParams.dataCfg, backendParams.vfPregParams.addrWidth))) 71 val toDataPathAfterDelay: MixedVec[MixedVec[DecoupledIO[IssueQueueIssueBundle]]] = MixedVec(params.issueBlockParams.map(_.genIssueDecoupledBundle)) 72 73 val vlWriteBack = new Bundle { 74 val vlIsZero = Input(Bool()) 75 val vlIsVlmax = Input(Bool()) 76 } 77 78 val fromSchedulers = new Bundle { 79 val wakeupVec: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpInValidBundle) 80 } 81 82 val toSchedulers = new Bundle { 83 val wakeupVec: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = params.genIQWakeUpOutValidBundle 84 } 85 86 val fromDataPath = new Bundle { 87 val resp: MixedVec[MixedVec[OGRespBundle]] = MixedVec(params.issueBlockParams.map(x => Flipped(x.genOGRespBundle))) 88 val og0Cancel = Input(ExuOH(backendParams.numExu)) 89 // Todo: remove this after no cancel signal from og1 90 val og1Cancel = Input(ExuOH(backendParams.numExu)) 91 val cancelToBusyTable = Vec(backendParams.numExu, Flipped(ValidIO(new CancelSignal))) 92 // just be compatible to old code 93 def apply(i: Int)(j: Int) = resp(i)(j) 94 } 95 96 val loadFinalIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.LdExuCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x))))))) 97 val memAddrIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.LdExuCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x))))))) 98 val vecLoadIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.VlduCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x))))))) 99 100 val ldCancel = Vec(backendParams.LduCnt + backendParams.HyuCnt, Flipped(new LoadCancelIO)) 101 102 val memIO = if (params.isMemSchd) Some(new Bundle { 103 val lsqEnqIO = Flipped(new LsqEnqIO) 104 }) else None 105 val fromMem = if (params.isMemSchd) Some(new Bundle { 106 val ldaFeedback = Flipped(Vec(params.LduCnt, new MemRSFeedbackIO)) 107 val staFeedback = Flipped(Vec(params.StaCnt, new MemRSFeedbackIO)) 108 val hyuFeedback = Flipped(Vec(params.HyuCnt, new MemRSFeedbackIO)) 109 val vstuFeedback = Flipped(Vec(params.VstuCnt, new MemRSFeedbackIO(isVector = true))) 110 val vlduFeedback = Flipped(Vec(params.VlduCnt, new MemRSFeedbackIO(isVector = true))) 111 val stIssuePtr = Input(new SqPtr()) 112 val lcommit = Input(UInt(log2Up(CommitWidth + 1).W)) 113 val scommit = Input(UInt(log2Ceil(EnsbufferWidth + 1).W)) // connected to `memBlock.io.sqDeq` instead of ROB 114 val wakeup = Vec(params.LdExuCnt, Flipped(Valid(new DynInst))) 115 val lqDeqPtr = Input(new LqPtr) 116 val sqDeqPtr = Input(new SqPtr) 117 // from lsq 118 val lqCancelCnt = Input(UInt(log2Up(LoadQueueSize + 1).W)) 119 val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W)) 120 val memWaitUpdateReq = Flipped(new MemWaitUpdateReq) 121 }) else None 122 val toMem = if (params.isMemSchd) Some(new Bundle { 123 val loadFastMatch = Output(Vec(params.LduCnt, new IssueQueueLoadBundle)) 124 }) else None 125 val fromOg2 = if(params.isVfSchd) Some(MixedVec(params.issueBlockParams.map(x => Flipped(x.genOG2RespBundle)))) else None 126} 127 128abstract class SchedulerImpBase(wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 129 extends LazyModuleImp(wrapper) 130 with HasXSParameter 131{ 132 val io = IO(new SchedulerIO()) 133 134 // alias 135 private val iqWakeUpInMap: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] = 136 io.fromSchedulers.wakeupVec.map(x => (x.bits.exuIdx, x)).toMap 137 private val schdType = params.schdType 138 139 // Modules 140 val dispatch2Iq: Dispatch2IqImp = wrapper.dispatch2Iq.module 141 val issueQueues: Seq[IssueQueueImp] = wrapper.issueQueue.map(_.module) 142 io.intIQValidNumVec := 0.U.asTypeOf(io.intIQValidNumVec) 143 io.fpIQValidNumVec := 0.U.asTypeOf(io.fpIQValidNumVec) 144 if (params.isIntSchd) { 145 dispatch2Iq.io.intIQValidNumVec.get := io.intIQValidNumVec 146 io.intIQValidNumVec := MixedVecInit(issueQueues.map(_.io.validCntDeqVec)) 147 } 148 else if (params.isFpSchd) { 149 dispatch2Iq.io.fpIQValidNumVec.get := io.fpIQValidNumVec 150 io.fpIQValidNumVec := MixedVecInit(issueQueues.map(_.io.validCntDeqVec)) 151 } 152 153 // valid count 154 dispatch2Iq.io.iqValidCnt := issueQueues.filter(_.params.StdCnt == 0).map(_.io.status.validCnt) 155 156 // BusyTable Modules 157 val intBusyTable = schdType match { 158 case IntScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numIntStateRead, wrapper.numIntStateWrite, IntPhyRegs, IntWB()))) 159 case _ => None 160 } 161 val fpBusyTable = schdType match { 162 case FpScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numFpStateRead, wrapper.numFpStateWrite, FpPhyRegs, FpWB()))) 163 case _ => None 164 } 165 val vfBusyTable = schdType match { 166 case VfScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numVfStateRead, wrapper.numVfStateWrite, VfPhyRegs, VfWB()))) 167 case _ => None 168 } 169 170 dispatch2Iq.io match { case dp2iq => 171 dp2iq.redirect <> io.fromCtrlBlock.flush 172 dp2iq.in <> io.fromDispatch.uops 173 dp2iq.readIntState.foreach(_ <> intBusyTable.get.io.read) 174 dp2iq.readFpState.foreach(_ <> fpBusyTable.get.io.read) 175 dp2iq.readVfState.foreach(_ <> vfBusyTable.get.io.read) 176 } 177 178 intBusyTable match { 179 case Some(bt) => 180 bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) => 181 btAllocPregs.valid := dpAllocPregs.isInt 182 btAllocPregs.bits := dpAllocPregs.preg 183 } 184 bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) => 185 wb.valid := io.intWriteBack(i).wen && io.intWriteBack(i).intWen 186 wb.bits := io.intWriteBack(i).addr 187 } 188 bt.io.wakeUp := io.fromSchedulers.wakeupVec 189 bt.io.cancel := io.fromDataPath.cancelToBusyTable 190 bt.io.ldCancel := io.ldCancel 191 case None => 192 } 193 194 fpBusyTable match { 195 case Some(bt) => 196 bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) => 197 btAllocPregs.valid := dpAllocPregs.isFp 198 btAllocPregs.bits := dpAllocPregs.preg 199 } 200 bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) => 201 wb.valid := io.fpWriteBack(i).wen && io.fpWriteBack(i).fpWen 202 wb.bits := io.fpWriteBack(i).addr 203 } 204 bt.io.wakeUp := io.fromSchedulers.wakeupVec 205 bt.io.cancel := io.fromDataPath.cancelToBusyTable 206 bt.io.ldCancel := io.ldCancel 207 case None => 208 } 209 210 vfBusyTable match { 211 case Some(bt) => 212 bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) => 213 btAllocPregs.valid := dpAllocPregs.isVec 214 btAllocPregs.bits := dpAllocPregs.preg 215 } 216 bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) => 217 wb.valid := io.vfWriteBack(i).wen && io.vfWriteBack(i).vecWen 218 wb.bits := io.vfWriteBack(i).addr 219 } 220 bt.io.wakeUp := io.fromSchedulers.wakeupVec 221 bt.io.cancel := io.fromDataPath.cancelToBusyTable 222 bt.io.ldCancel := io.ldCancel 223 case None => 224 } 225 226 val wakeupFromIntWBVec = Wire(params.genIntWBWakeUpSinkValidBundle) 227 val wakeupFromFpWBVec = Wire(params.genFpWBWakeUpSinkValidBundle) 228 val wakeupFromVfWBVec = Wire(params.genVfWBWakeUpSinkValidBundle) 229 230 wakeupFromIntWBVec.zip(io.intWriteBack).foreach { case (sink, source) => 231 sink.valid := source.wen 232 sink.bits.rfWen := source.intWen 233 sink.bits.fpWen := source.fpWen 234 sink.bits.vecWen := source.vecWen 235 sink.bits.pdest := source.addr 236 } 237 238 wakeupFromFpWBVec.zip(io.fpWriteBack).foreach { case (sink, source) => 239 sink.valid := source.wen 240 sink.bits.rfWen := source.intWen 241 sink.bits.fpWen := source.fpWen 242 sink.bits.vecWen := source.vecWen 243 sink.bits.pdest := source.addr 244 } 245 246 wakeupFromVfWBVec.zip(io.vfWriteBack).foreach { case (sink, source) => 247 sink.valid := source.wen 248 sink.bits.rfWen := source.intWen 249 sink.bits.fpWen := source.fpWen 250 sink.bits.vecWen := source.vecWen 251 sink.bits.pdest := source.addr 252 } 253 254 // Connect bundles having the same wakeup source 255 issueQueues.zipWithIndex.foreach { case(iq, i) => 256 iq.io.wakeupFromIQ.foreach { wakeUp => 257 val wakeUpIn = iqWakeUpInMap(wakeUp.bits.exuIdx) 258 val exuIdx = wakeUp.bits.exuIdx 259 println(s"[Backend] Connect wakeup exuIdx ${exuIdx}") 260 connectSamePort(wakeUp,wakeUpIn) 261 backendParams.connectWakeup(exuIdx) 262 if (backendParams.isCopyPdest(exuIdx)) { 263 println(s"[Backend] exuIdx ${exuIdx} use pdestCopy ${backendParams.getCopyPdestIndex(exuIdx)}") 264 wakeUp.bits.pdest := wakeUpIn.bits.pdestCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 265 if (wakeUpIn.bits.rfWenCopy.nonEmpty) wakeUp.bits.rfWen := wakeUpIn.bits.rfWenCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 266 if (wakeUpIn.bits.fpWenCopy.nonEmpty) wakeUp.bits.fpWen := wakeUpIn.bits.fpWenCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 267 if (wakeUpIn.bits.vecWenCopy.nonEmpty) wakeUp.bits.vecWen := wakeUpIn.bits.vecWenCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 268 if (wakeUpIn.bits.loadDependencyCopy.nonEmpty) wakeUp.bits.loadDependency := wakeUpIn.bits.loadDependencyCopy.get(backendParams.getCopyPdestIndex(exuIdx)) 269 } 270 if (iq.params.numIntSrc == 0) wakeUp.bits.rfWen := false.B 271 if (iq.params.numFpSrc == 0) wakeUp.bits.fpWen := false.B 272 if (iq.params.numVfSrc == 0) wakeUp.bits.vecWen := false.B 273 } 274 iq.io.og0Cancel := io.fromDataPath.og0Cancel 275 iq.io.og1Cancel := io.fromDataPath.og1Cancel 276 iq.io.ldCancel := io.ldCancel 277 } 278 279 // connect the vl writeback informatino to the issue queues 280 issueQueues.zipWithIndex.foreach { case(iq, i) => 281 iq.io.vlIsVlmax := io.vlWriteBack.vlIsVlmax 282 iq.io.vlIsZero := io.vlWriteBack.vlIsZero 283 } 284 285 private val iqWakeUpOutMap: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] = 286 issueQueues.flatMap(_.io.wakeupToIQ) 287 .map(x => (x.bits.exuIdx, x)) 288 .toMap 289 290 // Connect bundles having the same wakeup source 291 io.toSchedulers.wakeupVec.foreach { wakeUp => 292 wakeUp := iqWakeUpOutMap(wakeUp.bits.exuIdx) 293 } 294 295 io.toDataPathAfterDelay.zipWithIndex.foreach { case (toDpDy, i) => 296 toDpDy <> issueQueues(i).io.deqDelay 297 } 298 299 // Response 300 issueQueues.zipWithIndex.foreach { case (iq, i) => 301 iq.io.og0Resp.zipWithIndex.foreach { case (og0Resp, j) => 302 og0Resp := io.fromDataPath(i)(j).og0resp 303 } 304 iq.io.og1Resp.zipWithIndex.foreach { case (og1Resp, j) => 305 og1Resp := io.fromDataPath(i)(j).og1resp 306 } 307 iq.io.finalIssueResp.foreach(_.zipWithIndex.foreach { case (finalIssueResp, j) => 308 if (io.loadFinalIssueResp(i).isDefinedAt(j)) { 309 finalIssueResp := io.loadFinalIssueResp(i)(j) 310 } else { 311 finalIssueResp := 0.U.asTypeOf(finalIssueResp) 312 } 313 }) 314 iq.io.memAddrIssueResp.foreach(_.zipWithIndex.foreach { case (memAddrIssueResp, j) => 315 if (io.memAddrIssueResp(i).isDefinedAt(j)) { 316 memAddrIssueResp := io.memAddrIssueResp(i)(j) 317 } else { 318 memAddrIssueResp := 0.U.asTypeOf(memAddrIssueResp) 319 } 320 }) 321 iq.io.vecLoadIssueResp.foreach(_.zipWithIndex.foreach { case (resp, deqIdx) => 322 resp := io.vecLoadIssueResp(i)(deqIdx) 323 }) 324 if(params.isVfSchd) { 325 iq.io.og2Resp.get.zipWithIndex.foreach { case (og2Resp, exuIdx) => 326 og2Resp := io.fromOg2.get(i)(exuIdx) 327 } 328 } 329 iq.io.wbBusyTableRead := io.fromWbFuBusyTable.fuBusyTableRead(i) 330 io.wbFuBusyTable(i) := iq.io.wbBusyTableWrite 331 } 332 333 println(s"[Scheduler] io.fromSchedulers.wakeupVec: ${io.fromSchedulers.wakeupVec.map(x => backendParams.getExuName(x.bits.exuIdx))}") 334 println(s"[Scheduler] iqWakeUpInKeys: ${iqWakeUpInMap.keys}") 335 336 println(s"[Scheduler] iqWakeUpOutKeys: ${iqWakeUpOutMap.keys}") 337 println(s"[Scheduler] io.toSchedulers.wakeupVec: ${io.toSchedulers.wakeupVec.map(x => backendParams.getExuName(x.bits.exuIdx))}") 338} 339 340class SchedulerArithImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 341 extends SchedulerImpBase(wrapper) 342 with HasXSParameter 343{ 344// dontTouch(io.vfWbFuBusyTable) 345 println(s"[SchedulerArithImp] " + 346 s"has intBusyTable: ${intBusyTable.nonEmpty}, " + 347 s"has vfBusyTable: ${vfBusyTable.nonEmpty}") 348 349 issueQueues.zipWithIndex.foreach { case (iq, i) => 350 iq.io.flush <> io.fromCtrlBlock.flush 351 iq.io.enq <> dispatch2Iq.io.out(i) 352 val intWBIQ = params.schdType match { 353 case IntScheduler() => wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) 354 case FpScheduler() => wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) 355 case VfScheduler() => wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) 356 case _ => null 357 } 358 iq.io.wakeupFromWB.zip(intWBIQ).foreach{ case (sink, source) => sink := source} 359 } 360} 361 362// FIXME: Vector mem instructions may not be handled properly! 363class SchedulerMemImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters) 364 extends SchedulerImpBase(wrapper) 365 with HasXSParameter 366{ 367 println(s"[SchedulerMemImp] " + 368 s"has intBusyTable: ${intBusyTable.nonEmpty}, " + 369 s"has vfBusyTable: ${vfBusyTable.nonEmpty}") 370 371 val memAddrIQs = issueQueues.filter(_.params.isMemAddrIQ) 372 val stAddrIQs = issueQueues.filter(iq => iq.params.StaCnt > 0) // included in memAddrIQs 373 val ldAddrIQs = issueQueues.filter(iq => iq.params.LduCnt > 0) 374 val stDataIQs = issueQueues.filter(iq => iq.params.StdCnt > 0) 375 val vecMemIQs = issueQueues.filter(_.params.isVecMemIQ) 376 val (hyuIQs, hyuIQIdxs) = issueQueues.zipWithIndex.filter(_._1.params.HyuCnt > 0).unzip 377 378 println(s"[SchedulerMemImp] memAddrIQs.size: ${memAddrIQs.size}, enq.size: ${memAddrIQs.map(_.io.enq.size).sum}") 379 println(s"[SchedulerMemImp] stAddrIQs.size: ${stAddrIQs.size }, enq.size: ${stAddrIQs.map(_.io.enq.size).sum}") 380 println(s"[SchedulerMemImp] ldAddrIQs.size: ${ldAddrIQs.size }, enq.size: ${ldAddrIQs.map(_.io.enq.size).sum}") 381 println(s"[SchedulerMemImp] stDataIQs.size: ${stDataIQs.size }, enq.size: ${stDataIQs.map(_.io.enq.size).sum}") 382 println(s"[SchedulerMemImp] hyuIQs.size: ${hyuIQs.size }, enq.size: ${hyuIQs.map(_.io.enq.size).sum}") 383 require(memAddrIQs.nonEmpty && stDataIQs.nonEmpty) 384 385 io.toMem.get.loadFastMatch := 0.U.asTypeOf(io.toMem.get.loadFastMatch) // TODO: is still needed? 386 387 private val loadWakeUp = issueQueues.filter(_.params.LdExuCnt > 0).map(_.asInstanceOf[IssueQueueMemAddrImp].io.memIO.get.loadWakeUp).flatten 388 require(loadWakeUp.length == io.fromMem.get.wakeup.length) 389 loadWakeUp.zip(io.fromMem.get.wakeup).foreach(x => x._1 := x._2) 390 391 memAddrIQs.zipWithIndex.foreach { case (iq, i) => 392 iq.io.flush <> io.fromCtrlBlock.flush 393 iq.io.enq <> dispatch2Iq.io.out(i) 394 iq.io.wakeupFromWB.zip( 395 wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 396 wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) ++ 397 wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) 398 ).foreach{ case (sink, source) => sink := source} 399 } 400 401 ldAddrIQs.zipWithIndex.foreach { 402 case (imp: IssueQueueMemAddrImp, i) => 403 imp.io.memIO.get.feedbackIO.head := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO.head) 404 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 405 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 406 case _ => 407 } 408 409 stAddrIQs.zipWithIndex.foreach { 410 case (imp: IssueQueueMemAddrImp, i) => 411 imp.io.memIO.get.feedbackIO.head := io.fromMem.get.staFeedback(i) 412 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 413 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 414 case _ => 415 } 416 417 hyuIQs.zip(hyuIQIdxs).foreach { 418 case (imp: IssueQueueMemAddrImp, idx) => 419 imp.io.memIO.get.feedbackIO.head := io.fromMem.get.hyuFeedback.head 420 imp.io.memIO.get.feedbackIO(1) := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO(1)) 421 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 422 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 423 // TODO: refactor ditry code 424 imp.io.deqDelay(1).ready := false.B 425 io.toDataPathAfterDelay(idx)(1).valid := false.B 426 io.toDataPathAfterDelay(idx)(1).bits := 0.U.asTypeOf(io.toDataPathAfterDelay(idx)(1).bits) 427 case _ => 428 } 429 430 private val staIdxSeq = (stAddrIQs).map(iq => iq.params.idxInSchBlk) 431 private val hyaIdxSeq = (hyuIQs).map(iq => iq.params.idxInSchBlk) 432 433 println(s"[SchedulerMemImp] sta iq idx in memSchdBlock: $staIdxSeq") 434 println(s"[SchedulerMemImp] hya iq idx in memSchdBlock: $hyaIdxSeq") 435 436 private val staEnqs = stAddrIQs.map(_.io.enq).flatten 437 private val stdEnqs = stDataIQs.map(_.io.enq).flatten.take(staEnqs.size) 438 private val hyaEnqs = hyuIQs.map(_.io.enq).flatten 439 private val hydEnqs = stDataIQs.map(_.io.enq).flatten.drop(staEnqs.size) 440 441 require(staEnqs.size == stdEnqs.size, s"number of enq ports of store address IQs(${staEnqs.size}) " + 442 s"should be equal to number of enq ports of store data IQs(${stdEnqs.size})") 443 444 require(hyaEnqs.size == hydEnqs.size, s"number of enq ports of hybrid address IQs(${hyaEnqs.size}) " + 445 s"should be equal to number of enq ports of hybrid data IQs(${hydEnqs.size})") 446 447 val d2IqStaOut = dispatch2Iq.io.out.zipWithIndex.filter(staIdxSeq contains _._2).unzip._1.flatten 448 d2IqStaOut.zip(staEnqs).zip(stdEnqs).foreach{ case((dp, staIQ), stdIQ) => 449 val isAllReady = staIQ.ready && stdIQ.ready 450 dp.ready := isAllReady 451 staIQ.valid := dp.valid && isAllReady 452 stdIQ.valid := dp.valid && isAllReady && FuType.FuTypeOrR(dp.bits.fuType, FuType.stu, FuType.mou) 453 } 454 455 val d2IqHyaOut = dispatch2Iq.io.out.zipWithIndex.filter(hyaIdxSeq contains _._2).unzip._1.flatten 456 d2IqHyaOut.zip(hyaEnqs).zip(hydEnqs).foreach{ case((dp, hyaIQ), hydIQ) => 457 val isAllReady = hyaIQ.ready && hydIQ.ready 458 dp.ready := isAllReady 459 hyaIQ.valid := dp.valid && isAllReady 460 hydIQ.valid := dp.valid && isAllReady && FuType.FuTypeOrR(dp.bits.fuType, FuType.stu, FuType.mou) 461 } 462 463 stDataIQs.zipWithIndex.foreach { case (iq, i) => 464 iq.io.flush <> io.fromCtrlBlock.flush 465 iq.io.wakeupFromWB.zip( 466 wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 467 wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 468 wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 469 ).foreach{ case (sink, source) => sink := source} 470 } 471 472 (stdEnqs ++ hydEnqs).zip(staEnqs ++ hyaEnqs).zipWithIndex.foreach { case ((stdIQEnq, staIQEnq), i) => 473 stdIQEnq.bits := staIQEnq.bits 474 // Store data reuses store addr src(1) in dispatch2iq 475 // [dispatch2iq] --src*------src*(0)--> [staIQ|hyaIQ] 476 // \ 477 // ---src*(1)--> [stdIQ] 478 // Since the src(1) of sta is easier to get, stdIQEnq.bits.src*(0) is assigned to staIQEnq.bits.src*(1) 479 // instead of dispatch2Iq.io.out(x).bits.src*(1) 480 val stdIdx = 1 481 stdIQEnq.bits.srcState(0) := staIQEnq.bits.srcState(stdIdx) 482 stdIQEnq.bits.srcLoadDependency(0) := staIQEnq.bits.srcLoadDependency(1) 483 stdIQEnq.bits.srcType(0) := staIQEnq.bits.srcType(stdIdx) 484 stdIQEnq.bits.psrc(0) := staIQEnq.bits.psrc(stdIdx) 485 stdIQEnq.bits.sqIdx := staIQEnq.bits.sqIdx 486 } 487 488 vecMemIQs.foreach { 489 case imp: IssueQueueVecMemImp => 490 imp.io.memIO.get.sqDeqPtr.foreach(_ := io.fromMem.get.sqDeqPtr) 491 imp.io.memIO.get.lqDeqPtr.foreach(_ := io.fromMem.get.lqDeqPtr) 492 // not used 493 //imp.io.memIO.get.feedbackIO.head := io.fromMem.get.vstuFeedback.head // only vector store replay 494 // maybe not used 495 imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr 496 imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq 497 imp.io.wakeupFromWB.zip( 498 wakeupFromIntWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 499 wakeupFromFpWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++ 500 wakeupFromVfWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq 501 ).foreach{ case (sink, source) => sink := source} 502 503 case _ => 504 } 505 val vecMemFeedbackIO: Seq[MemRSFeedbackIO] = vecMemIQs.map { 506 case imp: IssueQueueVecMemImp => 507 imp.io.memIO.get.feedbackIO 508 }.flatten 509 assert(vecMemFeedbackIO.size == io.fromMem.get.vstuFeedback.size, "vecMemFeedback size dont match!") 510 vecMemFeedbackIO.zip(io.fromMem.get.vstuFeedback).foreach{ 511 case (sink, source) => 512 sink := source 513 } 514 515 val lsqEnqCtrl = Module(new LsqEnqCtrl) 516 517 lsqEnqCtrl.io.redirect <> io.fromCtrlBlock.flush 518 lsqEnqCtrl.io.enq <> dispatch2Iq.io.enqLsqIO.get 519 lsqEnqCtrl.io.lcommit := io.fromMem.get.lcommit 520 lsqEnqCtrl.io.scommit := io.fromMem.get.scommit 521 lsqEnqCtrl.io.lqCancelCnt := io.fromMem.get.lqCancelCnt 522 lsqEnqCtrl.io.sqCancelCnt := io.fromMem.get.sqCancelCnt 523 dispatch2Iq.io.lqFreeCount.get := lsqEnqCtrl.io.lqFreeCount 524 dispatch2Iq.io.sqFreeCount.get := lsqEnqCtrl.io.sqFreeCount 525 io.memIO.get.lsqEnqIO <> lsqEnqCtrl.io.enqLsq 526 527 dontTouch(io.vecLoadIssueResp) 528} 529