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