xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision 556c96d6b6ae6e43d3fb87ddfd73967483e62a97)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17package xiangshan.backend
18
19import org.chipsalliance.cde.config.Parameters
20import chisel3._
21import chisel3.util._
22import device.MsiInfoBundle
23import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
24import system.HasSoCParameter
25import utility._
26import utils.{HPerfMonitor, HasPerfEvents, PerfEvent}
27import xiangshan._
28import xiangshan.backend.Bundles.{DynInst, IssueQueueIQWakeUpBundle, LoadShouldCancel, MemExuInput, MemExuOutput, VPUCtrlSignals}
29import xiangshan.backend.ctrlblock.{DebugLSIO, LsTopdownInfo}
30import xiangshan.backend.datapath.DataConfig.{IntData, VecData, FpData}
31import xiangshan.backend.datapath.RdConfig.{IntRD, VfRD}
32import xiangshan.backend.datapath.WbConfig._
33import xiangshan.backend.datapath.DataConfig._
34import xiangshan.backend.datapath._
35import xiangshan.backend.dispatch.CoreDispatchTopDownIO
36import xiangshan.backend.exu.ExuBlock
37import xiangshan.backend.fu.vector.Bundles.{VConfig, VType}
38import xiangshan.backend.fu.{FenceIO, FenceToSbuffer, FuConfig, FuType, PFEvent, PerfCounterIO}
39import xiangshan.backend.issue.EntryBundles._
40import xiangshan.backend.issue.{CancelNetwork, Scheduler, SchedulerArithImp, SchedulerImpBase, SchedulerMemImp}
41import xiangshan.backend.rob.{RobCoreTopDownIO, RobDebugRollingIO, RobLsqIO, RobPtr}
42import xiangshan.frontend.{FtqPtr, FtqRead, PreDecodeInfo}
43import xiangshan.mem.{LqPtr, LsqEnqIO, SqPtr}
44
45import scala.collection.mutable
46
47class Backend(val params: BackendParams)(implicit p: Parameters) extends LazyModule
48  with HasXSParameter {
49
50  override def shouldBeInlined: Boolean = false
51
52  // check read & write port config
53  params.configChecks
54
55  /* Only update the idx in mem-scheduler here
56   * Idx in other schedulers can be updated the same way if needed
57   *
58   * Also note that we filter out the 'stData issue-queues' when counting
59   */
60  for ((ibp, idx) <- params.memSchdParams.get.issueBlockParams.filter(iq => iq.StdCnt == 0).zipWithIndex) {
61    ibp.updateIdx(idx)
62  }
63
64  println(params.iqWakeUpParams)
65
66  for ((schdCfg, i) <- params.allSchdParams.zipWithIndex) {
67    schdCfg.bindBackendParam(params)
68  }
69
70  for ((iqCfg, i) <- params.allIssueParams.zipWithIndex) {
71    iqCfg.bindBackendParam(params)
72  }
73
74  for ((exuCfg, i) <- params.allExuParams.zipWithIndex) {
75    exuCfg.bindBackendParam(params)
76    exuCfg.updateIQWakeUpConfigs(params.iqWakeUpParams)
77    exuCfg.updateExuIdx(i)
78  }
79
80  println("[Backend] ExuConfigs:")
81  for (exuCfg <- params.allExuParams) {
82    val fuConfigs = exuCfg.fuConfigs
83    val wbPortConfigs = exuCfg.wbPortConfigs
84    val immType = exuCfg.immType
85
86    println("[Backend]   " +
87      s"${exuCfg.name}: " +
88      (if (exuCfg.fakeUnit) "fake, " else "") +
89      (if (exuCfg.hasLoadFu || exuCfg.hasHyldaFu) s"LdExuIdx(${backendParams.getLdExuIdx(exuCfg)})" else "") +
90      s"${fuConfigs.map(_.name).mkString("fu(s): {", ",", "}")}, " +
91      s"${wbPortConfigs.mkString("wb: {", ",", "}")}, " +
92      s"${immType.map(SelImm.mkString(_)).mkString("imm: {", ",", "}")}, " +
93      s"latMax(${exuCfg.latencyValMax}), ${exuCfg.fuLatancySet.mkString("lat: {", ",", "}")}, " +
94      s"srcReg(${exuCfg.numRegSrc})"
95    )
96    require(
97      wbPortConfigs.collectFirst { case x: IntWB => x }.nonEmpty ==
98        fuConfigs.map(_.writeIntRf).reduce(_ || _),
99      s"${exuCfg.name} int wb port has no priority"
100    )
101    require(
102      wbPortConfigs.collectFirst { case x: FpWB => x }.nonEmpty ==
103        fuConfigs.map(x => x.writeFpRf).reduce(_ || _),
104      s"${exuCfg.name} fp wb port has no priority"
105    )
106    require(
107      wbPortConfigs.collectFirst { case x: VfWB => x }.nonEmpty ==
108        fuConfigs.map(x => x.writeVecRf).reduce(_ || _),
109      s"${exuCfg.name} vec wb port has no priority"
110    )
111  }
112
113  println(s"[Backend] all fu configs")
114  for (cfg <- FuConfig.allConfigs) {
115    println(s"[Backend]   $cfg")
116  }
117
118  println(s"[Backend] Int RdConfigs: ExuName(Priority)")
119  for ((port, seq) <- params.getRdPortParams(IntData())) {
120    println(s"[Backend]   port($port): ${seq.map(x => params.getExuName(x._1) + "(" + x._2.toString + ")").mkString(",")}")
121  }
122
123  println(s"[Backend] Int WbConfigs: ExuName(Priority)")
124  for ((port, seq) <- params.getWbPortParams(IntData())) {
125    println(s"[Backend]   port($port): ${seq.map(x => params.getExuName(x._1) + "(" + x._2.toString + ")").mkString(",")}")
126  }
127
128  println(s"[Backend] Fp RdConfigs: ExuName(Priority)")
129  for ((port, seq) <- params.getRdPortParams(FpData())) {
130    println(s"[Backend]   port($port): ${seq.map(x => params.getExuName(x._1) + "(" + x._2.toString + ")").mkString(",")}")
131  }
132
133  println(s"[Backend] Fp WbConfigs: ExuName(Priority)")
134  for ((port, seq) <- params.getWbPortParams(FpData())) {
135    println(s"[Backend]   port($port): ${seq.map(x => params.getExuName(x._1) + "(" + x._2.toString + ")").mkString(",")}")
136  }
137
138  println(s"[Backend] Vf RdConfigs: ExuName(Priority)")
139  for ((port, seq) <- params.getRdPortParams(VecData())) {
140    println(s"[Backend]   port($port): ${seq.map(x => params.getExuName(x._1) + "(" + x._2.toString + ")").mkString(",")}")
141  }
142
143  println(s"[Backend] Vf WbConfigs: ExuName(Priority)")
144  for ((port, seq) <- params.getWbPortParams(VecData())) {
145    println(s"[Backend]   port($port): ${seq.map(x => params.getExuName(x._1) + "(" + x._2.toString + ")").mkString(",")}")
146  }
147
148  println(s"[Backend] Dispatch Configs:")
149  println(s"[Backend] Load IQ enq width(${params.numLoadDp}), Store IQ enq width(${params.numStoreDp})")
150  println(s"[Backend] Load DP width(${LSQLdEnqWidth}), Store DP width(${LSQStEnqWidth})")
151
152  params.updateCopyPdestInfo
153  println(s"[Backend] copyPdestInfo ${params.copyPdestInfo}")
154  params.allExuParams.map(_.copyNum)
155  val ctrlBlock = LazyModule(new CtrlBlock(params))
156  val pcTargetMem = LazyModule(new PcTargetMem(params))
157  val intScheduler = params.intSchdParams.map(x => LazyModule(new Scheduler(x)))
158  val fpScheduler = params.fpSchdParams.map(x => LazyModule(new Scheduler(x)))
159  val vfScheduler = params.vfSchdParams.map(x => LazyModule(new Scheduler(x)))
160  val memScheduler = params.memSchdParams.map(x => LazyModule(new Scheduler(x)))
161  val dataPath = LazyModule(new DataPath(params))
162  val intExuBlock = params.intSchdParams.map(x => LazyModule(new ExuBlock(x)))
163  val fpExuBlock = params.fpSchdParams.map(x => LazyModule(new ExuBlock(x)))
164  val vfExuBlock = params.vfSchdParams.map(x => LazyModule(new ExuBlock(x)))
165  val wbFuBusyTable = LazyModule(new WbFuBusyTable(params))
166
167  lazy val module = new BackendImp(this)
168}
169
170class BackendImp(override val wrapper: Backend)(implicit p: Parameters) extends LazyModuleImp(wrapper)
171  with HasXSParameter
172  with HasPerfEvents {
173  implicit private val params: BackendParams = wrapper.params
174
175  val io = IO(new BackendIO()(p, wrapper.params))
176
177  private val ctrlBlock = wrapper.ctrlBlock.module
178  private val pcTargetMem = wrapper.pcTargetMem.module
179  private val intScheduler: SchedulerImpBase = wrapper.intScheduler.get.module
180  private val fpScheduler = wrapper.fpScheduler.get.module
181  private val vfScheduler = wrapper.vfScheduler.get.module
182  private val memScheduler = wrapper.memScheduler.get.module
183  private val dataPath = wrapper.dataPath.module
184  private val intExuBlock = wrapper.intExuBlock.get.module
185  private val fpExuBlock = wrapper.fpExuBlock.get.module
186  private val vfExuBlock = wrapper.vfExuBlock.get.module
187  private val og2ForVector = Module(new Og2ForVector(params))
188  private val bypassNetwork = Module(new BypassNetwork)
189  private val wbDataPath = Module(new WbDataPath(params))
190  private val wbFuBusyTable = wrapper.wbFuBusyTable.module
191
192  private val iqWakeUpMappedBundle: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] = (
193    intScheduler.io.toSchedulers.wakeupVec ++
194      fpScheduler.io.toSchedulers.wakeupVec ++
195      vfScheduler.io.toSchedulers.wakeupVec ++
196      memScheduler.io.toSchedulers.wakeupVec
197    ).map(x => (x.bits.exuIdx, x)).toMap
198
199  println(s"[Backend] iq wake up keys: ${iqWakeUpMappedBundle.keys}")
200
201  wbFuBusyTable.io.in.intSchdBusyTable := intScheduler.io.wbFuBusyTable
202  wbFuBusyTable.io.in.fpSchdBusyTable := fpScheduler.io.wbFuBusyTable
203  wbFuBusyTable.io.in.vfSchdBusyTable := vfScheduler.io.wbFuBusyTable
204  wbFuBusyTable.io.in.memSchdBusyTable := memScheduler.io.wbFuBusyTable
205  intScheduler.io.fromWbFuBusyTable.fuBusyTableRead := wbFuBusyTable.io.out.intRespRead
206  fpScheduler.io.fromWbFuBusyTable.fuBusyTableRead := wbFuBusyTable.io.out.fpRespRead
207  vfScheduler.io.fromWbFuBusyTable.fuBusyTableRead := wbFuBusyTable.io.out.vfRespRead
208  memScheduler.io.fromWbFuBusyTable.fuBusyTableRead := wbFuBusyTable.io.out.memRespRead
209  dataPath.io.wbConfictRead := wbFuBusyTable.io.out.wbConflictRead
210
211  private val og1Cancel = dataPath.io.og1Cancel
212  private val og0Cancel = dataPath.io.og0Cancel
213  private val vlIsZero = intExuBlock.io.vlIsZero.get
214  private val vlIsVlmax = intExuBlock.io.vlIsVlmax.get
215
216  ctrlBlock.io.intIQValidNumVec := intScheduler.io.intIQValidNumVec
217  ctrlBlock.io.fpIQValidNumVec := fpScheduler.io.fpIQValidNumVec
218  ctrlBlock.io.fromTop.hartId := io.fromTop.hartId
219  ctrlBlock.io.frontend <> io.frontend
220  ctrlBlock.io.fromCSR.toDecode := intExuBlock.io.csrToDecode.get
221  ctrlBlock.io.fromWB.wbData <> wbDataPath.io.toCtrlBlock.writeback
222  ctrlBlock.io.fromMem.stIn <> io.mem.stIn
223  ctrlBlock.io.fromMem.violation <> io.mem.memoryViolation
224  ctrlBlock.io.lqCanAccept := io.mem.lqCanAccept
225  ctrlBlock.io.sqCanAccept := io.mem.sqCanAccept
226  ctrlBlock.io.csrCtrl <> intExuBlock.io.csrio.get.customCtrl
227  ctrlBlock.io.robio.csr.intrBitSet := intExuBlock.io.csrio.get.interrupt
228  ctrlBlock.io.robio.csr.trapTarget := intExuBlock.io.csrio.get.trapTarget
229  ctrlBlock.io.robio.csr.isXRet := intExuBlock.io.csrio.get.isXRet
230  ctrlBlock.io.robio.csr.wfiEvent := intExuBlock.io.csrio.get.wfi_event
231  ctrlBlock.io.robio.lsq <> io.mem.robLsqIO
232  ctrlBlock.io.robio.lsTopdownInfo <> io.mem.lsTopdownInfo
233  ctrlBlock.io.robio.debug_ls <> io.mem.debugLS
234  ctrlBlock.io.debugEnqLsq.canAccept := io.mem.lsqEnqIO.canAccept
235  ctrlBlock.io.debugEnqLsq.resp := io.mem.lsqEnqIO.resp
236  ctrlBlock.io.debugEnqLsq.req := memScheduler.io.memIO.get.lsqEnqIO.req
237  ctrlBlock.io.debugEnqLsq.needAlloc := memScheduler.io.memIO.get.lsqEnqIO.needAlloc
238  ctrlBlock.io.debugEnqLsq.iqAccept := memScheduler.io.memIO.get.lsqEnqIO.iqAccept
239
240  intScheduler.io.fromTop.hartId := io.fromTop.hartId
241  intScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush
242  intScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs
243  intScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.intUops
244  intScheduler.io.intWriteBack := wbDataPath.io.toIntPreg
245  intScheduler.io.fpWriteBack := 0.U.asTypeOf(intScheduler.io.fpWriteBack)
246  intScheduler.io.vfWriteBack := 0.U.asTypeOf(intScheduler.io.vfWriteBack)
247  intScheduler.io.v0WriteBack := 0.U.asTypeOf(intScheduler.io.v0WriteBack)
248  intScheduler.io.vlWriteBack := 0.U.asTypeOf(intScheduler.io.vlWriteBack)
249  intScheduler.io.fromDataPath.resp := dataPath.io.toIntIQ
250  intScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) }
251  intScheduler.io.fromDataPath.og0Cancel := og0Cancel
252  intScheduler.io.fromDataPath.og1Cancel := og1Cancel
253  intScheduler.io.ldCancel := io.mem.ldCancel
254  intScheduler.io.fromDataPath.replaceRCIdx.get := dataPath.io.toWakeupQueueRCIdx.take(params.getIntExuRCWriteSize)
255  intScheduler.io.vlWriteBackInfo.vlIsZero := false.B
256  intScheduler.io.vlWriteBackInfo.vlIsVlmax := false.B
257
258  fpScheduler.io.fromTop.hartId := io.fromTop.hartId
259  fpScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush
260  fpScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs
261  fpScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.fpUops
262  fpScheduler.io.intWriteBack := 0.U.asTypeOf(fpScheduler.io.intWriteBack)
263  fpScheduler.io.fpWriteBack := wbDataPath.io.toFpPreg
264  fpScheduler.io.vfWriteBack := 0.U.asTypeOf(fpScheduler.io.vfWriteBack)
265  fpScheduler.io.v0WriteBack := 0.U.asTypeOf(fpScheduler.io.v0WriteBack)
266  fpScheduler.io.vlWriteBack := 0.U.asTypeOf(fpScheduler.io.vlWriteBack)
267  fpScheduler.io.fromDataPath.resp := dataPath.io.toFpIQ
268  fpScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) }
269  fpScheduler.io.fromDataPath.og0Cancel := og0Cancel
270  fpScheduler.io.fromDataPath.og1Cancel := og1Cancel
271  fpScheduler.io.ldCancel := io.mem.ldCancel
272  fpScheduler.io.vlWriteBackInfo.vlIsZero := false.B
273  fpScheduler.io.vlWriteBackInfo.vlIsVlmax := false.B
274
275  memScheduler.io.fromTop.hartId := io.fromTop.hartId
276  memScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush
277  memScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs
278  memScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.memUops
279  memScheduler.io.intWriteBack := wbDataPath.io.toIntPreg
280  memScheduler.io.fpWriteBack := wbDataPath.io.toFpPreg
281  memScheduler.io.vfWriteBack := wbDataPath.io.toVfPreg
282  memScheduler.io.v0WriteBack := wbDataPath.io.toV0Preg
283  memScheduler.io.vlWriteBack := wbDataPath.io.toVlPreg
284  memScheduler.io.fromMem.get.scommit := io.mem.sqDeq
285  memScheduler.io.fromMem.get.lcommit := io.mem.lqDeq
286  memScheduler.io.fromMem.get.wakeup := io.mem.wakeup
287  memScheduler.io.fromMem.get.sqDeqPtr := io.mem.sqDeqPtr
288  memScheduler.io.fromMem.get.lqDeqPtr := io.mem.lqDeqPtr
289  memScheduler.io.fromMem.get.sqCancelCnt := io.mem.sqCancelCnt
290  memScheduler.io.fromMem.get.lqCancelCnt := io.mem.lqCancelCnt
291  memScheduler.io.fromMem.get.stIssuePtr := io.mem.stIssuePtr
292  require(memScheduler.io.fromMem.get.memWaitUpdateReq.robIdx.length == io.mem.stIn.length)
293  memScheduler.io.fromMem.get.memWaitUpdateReq.robIdx.zip(io.mem.stIn).foreach { case (sink, source) =>
294    sink.valid := source.valid
295    sink.bits  := source.bits.robIdx
296  }
297  memScheduler.io.fromMem.get.memWaitUpdateReq.sqIdx := DontCare // TODO
298  memScheduler.io.fromDataPath.resp := dataPath.io.toMemIQ
299  memScheduler.io.fromMem.get.ldaFeedback := io.mem.ldaIqFeedback
300  memScheduler.io.fromMem.get.staFeedback := io.mem.staIqFeedback
301  memScheduler.io.fromMem.get.hyuFeedback := io.mem.hyuIqFeedback
302  memScheduler.io.fromMem.get.vstuFeedback := io.mem.vstuIqFeedback
303  memScheduler.io.fromMem.get.vlduFeedback := io.mem.vlduIqFeedback
304  memScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) }
305  memScheduler.io.fromDataPath.og0Cancel := og0Cancel
306  memScheduler.io.fromDataPath.og1Cancel := og1Cancel
307  memScheduler.io.ldCancel := io.mem.ldCancel
308  memScheduler.io.fromDataPath.replaceRCIdx.get := dataPath.io.toWakeupQueueRCIdx.takeRight(params.getMemExuRCWriteSize)
309  memScheduler.io.vlWriteBackInfo.vlIsZero := vlIsZero
310  memScheduler.io.vlWriteBackInfo.vlIsVlmax := vlIsVlmax
311  memScheduler.io.fromOg2Resp.get := og2ForVector.io.toMemIQOg2Resp
312
313  vfScheduler.io.fromTop.hartId := io.fromTop.hartId
314  vfScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush
315  vfScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs
316  vfScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.vfUops
317  vfScheduler.io.intWriteBack := 0.U.asTypeOf(vfScheduler.io.intWriteBack)
318  vfScheduler.io.fpWriteBack := 0.U.asTypeOf(vfScheduler.io.fpWriteBack)
319  vfScheduler.io.vfWriteBack := wbDataPath.io.toVfPreg
320  vfScheduler.io.v0WriteBack := wbDataPath.io.toV0Preg
321  vfScheduler.io.vlWriteBack := wbDataPath.io.toVlPreg
322  vfScheduler.io.fromDataPath.resp := dataPath.io.toVfIQ
323  vfScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) }
324  vfScheduler.io.fromDataPath.og0Cancel := og0Cancel
325  vfScheduler.io.fromDataPath.og1Cancel := og1Cancel
326  vfScheduler.io.ldCancel := io.mem.ldCancel
327  vfScheduler.io.vlWriteBackInfo.vlIsZero := vlIsZero
328  vfScheduler.io.vlWriteBackInfo.vlIsVlmax := vlIsVlmax
329  vfScheduler.io.fromOg2Resp.get := og2ForVector.io.toVfIQOg2Resp
330
331  dataPath.io.hartId := io.fromTop.hartId
332  dataPath.io.flush := ctrlBlock.io.toDataPath.flush
333
334  dataPath.io.fromIntIQ <> intScheduler.io.toDataPathAfterDelay
335  dataPath.io.fromFpIQ <> fpScheduler.io.toDataPathAfterDelay
336  dataPath.io.fromVfIQ <> vfScheduler.io.toDataPathAfterDelay
337  dataPath.io.fromMemIQ <> memScheduler.io.toDataPathAfterDelay
338
339  dataPath.io.ldCancel := io.mem.ldCancel
340
341  println(s"[Backend] wbDataPath.io.toIntPreg: ${wbDataPath.io.toIntPreg.size}, dataPath.io.fromIntWb: ${dataPath.io.fromIntWb.size}")
342  println(s"[Backend] wbDataPath.io.toVfPreg: ${wbDataPath.io.toVfPreg.size}, dataPath.io.fromFpWb: ${dataPath.io.fromVfWb.size}")
343  dataPath.io.fromIntWb := wbDataPath.io.toIntPreg
344  dataPath.io.fromFpWb := wbDataPath.io.toFpPreg
345  dataPath.io.fromVfWb := wbDataPath.io.toVfPreg
346  dataPath.io.fromV0Wb := wbDataPath.io.toV0Preg
347  dataPath.io.fromVlWb := wbDataPath.io.toVlPreg
348  dataPath.io.diffIntRat.foreach(_ := ctrlBlock.io.diff_int_rat.get)
349  dataPath.io.diffFpRat .foreach(_ := ctrlBlock.io.diff_fp_rat.get)
350  dataPath.io.diffVecRat.foreach(_ := ctrlBlock.io.diff_vec_rat.get)
351  dataPath.io.diffV0Rat .foreach(_ := ctrlBlock.io.diff_v0_rat.get)
352  dataPath.io.diffVlRat .foreach(_ := ctrlBlock.io.diff_vl_rat.get)
353  dataPath.io.fromBypassNetwork := bypassNetwork.io.toDataPath
354
355  og2ForVector.io.flush := ctrlBlock.io.toDataPath.flush
356  og2ForVector.io.ldCancel := io.mem.ldCancel
357  og2ForVector.io.fromOg1VfArith <> dataPath.io.toVecExu
358  og2ForVector.io.fromOg1VecMem.zip(dataPath.io.toMemExu.zip(params.memSchdParams.get.issueBlockParams).filter(_._2.needOg2Resp).map(_._1))
359    .foreach {
360      case (og1Mem, datapathMem) => og1Mem <> datapathMem
361    }
362  og2ForVector.io.fromOg1ImmInfo := dataPath.io.og1ImmInfo.zip(params.allExuParams).filter(_._2.needOg2).map(_._1)
363
364  println(s"[Backend] BypassNetwork OG1 Mem Size: ${bypassNetwork.io.fromDataPath.mem.zip(params.memSchdParams.get.issueBlockParams).filterNot(_._2.needOg2Resp).size}")
365  println(s"[Backend] BypassNetwork OG2 Mem Size: ${bypassNetwork.io.fromDataPath.mem.zip(params.memSchdParams.get.issueBlockParams).filter(_._2.needOg2Resp).size}")
366  println(s"[Backend] bypassNetwork.io.fromDataPath.mem: ${bypassNetwork.io.fromDataPath.mem.size}, dataPath.io.toMemExu: ${dataPath.io.toMemExu.size}")
367  bypassNetwork.io.fromDataPath.int <> dataPath.io.toIntExu
368  bypassNetwork.io.fromDataPath.fp <> dataPath.io.toFpExu
369  bypassNetwork.io.fromDataPath.vf <> og2ForVector.io.toVfArithExu
370  bypassNetwork.io.fromDataPath.mem.lazyZip(params.memSchdParams.get.issueBlockParams).lazyZip(dataPath.io.toMemExu).filterNot(_._2.needOg2Resp)
371    .map(x => (x._1, x._3)).foreach {
372      case (bypassMem, datapathMem) => bypassMem <> datapathMem
373    }
374  bypassNetwork.io.fromDataPath.mem.zip(params.memSchdParams.get.issueBlockParams).filter(_._2.needOg2Resp).map(_._1)
375    .zip(og2ForVector.io.toVecMemExu).foreach {
376      case (bypassMem, og2Mem) => bypassMem <> og2Mem
377    }
378  bypassNetwork.io.fromDataPath.immInfo := dataPath.io.og1ImmInfo
379  bypassNetwork.io.fromDataPath.immInfo.zip(params.allExuParams).filter(_._2.needOg2).map(_._1)
380    .zip(og2ForVector.io.toBypassNetworkImmInfo).foreach {
381      case (immInfo, og2ImmInfo) => immInfo := og2ImmInfo
382    }
383  bypassNetwork.io.fromDataPath.rcData := dataPath.io.toBypassNetworkRCData
384  bypassNetwork.io.fromExus.connectExuOutput(_.int)(intExuBlock.io.out)
385  bypassNetwork.io.fromExus.connectExuOutput(_.fp)(fpExuBlock.io.out)
386  bypassNetwork.io.fromExus.connectExuOutput(_.vf)(vfExuBlock.io.out)
387
388  require(bypassNetwork.io.fromExus.mem.flatten.size == io.mem.writeBack.size,
389    s"bypassNetwork.io.fromExus.mem.flatten.size(${bypassNetwork.io.fromExus.mem.flatten.size}: ${bypassNetwork.io.fromExus.mem.map(_.size)}, " +
390    s"io.mem.writeback(${io.mem.writeBack.size})"
391  )
392  bypassNetwork.io.fromExus.mem.flatten.zip(io.mem.writeBack).foreach { case (sink, source) =>
393    sink.valid := source.valid
394    sink.bits.intWen := source.bits.uop.rfWen && FuType.isLoad(source.bits.uop.fuType)
395    sink.bits.pdest := source.bits.uop.pdest
396    sink.bits.data := source.bits.data
397  }
398
399
400  intExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush
401  for (i <- 0 until intExuBlock.io.in.length) {
402    for (j <- 0 until intExuBlock.io.in(i).length) {
403      val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.int(i)(j).bits.loadDependency, io.mem.ldCancel)
404      NewPipelineConnect(
405        bypassNetwork.io.toExus.int(i)(j), intExuBlock.io.in(i)(j), intExuBlock.io.in(i)(j).fire,
406        Mux(
407          bypassNetwork.io.toExus.int(i)(j).fire,
408          bypassNetwork.io.toExus.int(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel,
409          intExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush)
410        ),
411        Option("bypassNetwork2intExuBlock")
412      )
413    }
414  }
415
416  pcTargetMem.io.fromFrontendFtq := io.frontend.fromFtq
417  pcTargetMem.io.toDataPath <> dataPath.io.fromPcTargetMem
418
419  private val csrin = intExuBlock.io.csrin.get
420  csrin.hartId := io.fromTop.hartId
421  csrin.msiInfo.valid := RegNext(io.fromTop.msiInfo.valid)
422  csrin.msiInfo.bits := RegEnable(io.fromTop.msiInfo.bits, io.fromTop.msiInfo.valid)
423  csrin.clintTime.valid := RegNext(io.fromTop.clintTime.valid)
424  csrin.clintTime.bits := RegEnable(io.fromTop.clintTime.bits, io.fromTop.clintTime.valid)
425  csrin.trapInstInfo := ctrlBlock.io.toCSR.trapInstInfo
426
427  private val csrio = intExuBlock.io.csrio.get
428  csrio.hartId := io.fromTop.hartId
429  csrio.fpu.fflags := ctrlBlock.io.robio.csr.fflags
430  csrio.fpu.isIllegal := false.B // Todo: remove it
431  csrio.fpu.dirty_fs := ctrlBlock.io.robio.csr.dirty_fs
432  csrio.vpu <> WireDefault(0.U.asTypeOf(csrio.vpu)) // Todo
433
434  val fromIntExuVsetVType = intExuBlock.io.vtype.getOrElse(0.U.asTypeOf((Valid(new VType))))
435  val fromVfExuVsetVType = vfExuBlock.io.vtype.getOrElse(0.U.asTypeOf((Valid(new VType))))
436  val fromVsetVType = Mux(fromIntExuVsetVType.valid, fromIntExuVsetVType.bits, fromVfExuVsetVType.bits)
437  val vsetvlVType = RegEnable(fromVsetVType, 0.U.asTypeOf(new VType), fromIntExuVsetVType.valid || fromVfExuVsetVType.valid)
438  ctrlBlock.io.toDecode.vsetvlVType := vsetvlVType
439
440  val commitVType = ctrlBlock.io.robio.commitVType.vtype
441  val hasVsetvl = ctrlBlock.io.robio.commitVType.hasVsetvl
442  val vtype = VType.toVtypeStruct(Mux(hasVsetvl, vsetvlVType, commitVType.bits)).asUInt
443
444  // csr not store the value of vl, so when using difftest we assign the value of vl to debugVl
445  val debugVl_s0 = WireInit(UInt(VlData().dataWidth.W), 0.U)
446  val debugVl_s1 = WireInit(UInt(VlData().dataWidth.W), 0.U)
447  debugVl_s0 := dataPath.io.diffVl.getOrElse(0.U.asTypeOf(UInt(VlData().dataWidth.W)))
448  debugVl_s1 := RegNext(debugVl_s0)
449  csrio.vpu.set_vxsat := ctrlBlock.io.robio.csr.vxsat
450  csrio.vpu.set_vstart.valid := ctrlBlock.io.robio.csr.vstart.valid
451  csrio.vpu.set_vstart.bits := ctrlBlock.io.robio.csr.vstart.bits
452  ctrlBlock.io.toDecode.vstart := csrio.vpu.vstart
453  //Todo here need change design
454  csrio.vpu.set_vtype.valid := commitVType.valid
455  csrio.vpu.set_vtype.bits := ZeroExt(vtype, XLEN)
456  csrio.vpu.vl := ZeroExt(debugVl_s1, XLEN)
457  csrio.vpu.dirty_vs := ctrlBlock.io.robio.csr.dirty_vs
458  csrio.exception := ctrlBlock.io.robio.exception
459  csrio.robDeqPtr := ctrlBlock.io.robio.robDeqPtr
460  csrio.memExceptionVAddr := io.mem.exceptionAddr.vaddr
461  csrio.memExceptionGPAddr := io.mem.exceptionAddr.gpaddr
462  csrio.externalInterrupt := RegNext(io.fromTop.externalInterrupt)
463  csrio.perf <> io.perf
464  csrio.perf.retiredInstr <> ctrlBlock.io.robio.csr.perfinfo.retiredInstr
465  csrio.perf.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo
466  private val fenceio = intExuBlock.io.fenceio.get
467  io.fenceio <> fenceio
468
469  // to fpExuBlock
470  fpExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush
471  for (i <- 0 until fpExuBlock.io.in.length) {
472    for (j <- 0 until fpExuBlock.io.in(i).length) {
473      val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.fp(i)(j).bits.loadDependency, io.mem.ldCancel)
474      NewPipelineConnect(
475        bypassNetwork.io.toExus.fp(i)(j), fpExuBlock.io.in(i)(j), fpExuBlock.io.in(i)(j).fire,
476        Mux(
477          bypassNetwork.io.toExus.fp(i)(j).fire,
478          bypassNetwork.io.toExus.fp(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel,
479          fpExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush)
480        ),
481        Option("bypassNetwork2fpExuBlock")
482      )
483    }
484  }
485
486  vfExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush
487  for (i <- 0 until vfExuBlock.io.in.size) {
488    for (j <- 0 until vfExuBlock.io.in(i).size) {
489      val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.vf(i)(j).bits.loadDependency, io.mem.ldCancel)
490      NewPipelineConnect(
491        bypassNetwork.io.toExus.vf(i)(j), vfExuBlock.io.in(i)(j), vfExuBlock.io.in(i)(j).fire,
492        Mux(
493          bypassNetwork.io.toExus.vf(i)(j).fire,
494          bypassNetwork.io.toExus.vf(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel,
495          vfExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush)
496        ),
497        Option("bypassNetwork2vfExuBlock")
498      )
499
500    }
501  }
502
503  intExuBlock.io.frm.foreach(_ := csrio.fpu.frm)
504  fpExuBlock.io.frm.foreach(_ := csrio.fpu.frm)
505  fpExuBlock.io.vxrm.foreach(_ := csrio.vpu.vxrm)
506  vfExuBlock.io.frm.foreach(_ := csrio.fpu.frm)
507  vfExuBlock.io.vxrm.foreach(_ := csrio.vpu.vxrm)
508
509  wbDataPath.io.flush := ctrlBlock.io.redirect
510  wbDataPath.io.fromTop.hartId := io.fromTop.hartId
511  wbDataPath.io.fromIntExu <> intExuBlock.io.out
512  wbDataPath.io.fromFpExu <> fpExuBlock.io.out
513  wbDataPath.io.fromVfExu <> vfExuBlock.io.out
514  wbDataPath.io.fromMemExu.flatten.zip(io.mem.writeBack).foreach { case (sink, source) =>
515    sink.valid := source.valid
516    source.ready := sink.ready
517    sink.bits.data   := VecInit(Seq.fill(sink.bits.params.wbPathNum)(source.bits.data))
518    sink.bits.pdest  := source.bits.uop.pdest
519    sink.bits.robIdx := source.bits.uop.robIdx
520    sink.bits.intWen.foreach(_ := source.bits.uop.rfWen)
521    sink.bits.fpWen.foreach(_ := source.bits.uop.fpWen)
522    sink.bits.vecWen.foreach(_ := source.bits.uop.vecWen)
523    sink.bits.v0Wen.foreach(_ := source.bits.uop.v0Wen)
524    sink.bits.vlWen.foreach(_ := source.bits.uop.vlWen)
525    sink.bits.exceptionVec.foreach(_ := source.bits.uop.exceptionVec)
526    sink.bits.flushPipe.foreach(_ := source.bits.uop.flushPipe)
527    sink.bits.replay.foreach(_ := source.bits.uop.replayInst)
528    sink.bits.debug := source.bits.debug
529    sink.bits.debugInfo := source.bits.uop.debugInfo
530    sink.bits.lqIdx.foreach(_ := source.bits.uop.lqIdx)
531    sink.bits.sqIdx.foreach(_ := source.bits.uop.sqIdx)
532    sink.bits.predecodeInfo.foreach(_ := source.bits.uop.preDecodeInfo)
533    sink.bits.vls.foreach(x => {
534      x.vdIdx := source.bits.vdIdx.get
535      x.vdIdxInField := source.bits.vdIdxInField.get
536      x.vpu   := source.bits.uop.vpu
537      x.oldVdPsrc := source.bits.uop.psrc(2)
538      x.isIndexed := VlduType.isIndexed(source.bits.uop.fuOpType)
539      x.isMasked := VlduType.isMasked(source.bits.uop.fuOpType)
540    })
541    sink.bits.trigger.foreach(_ := source.bits.uop.trigger)
542  }
543
544  // to mem
545  private val memIssueParams = params.memSchdParams.get.issueBlockParams
546  private val memExuBlocksHasLDU = memIssueParams.map(_.exuBlockParams.map(x => x.hasLoadFu || x.hasHyldaFu))
547  private val memExuBlocksHasVecLoad = memIssueParams.map(_.exuBlockParams.map(x => x.hasVLoadFu))
548  println(s"[Backend] memExuBlocksHasLDU: $memExuBlocksHasLDU")
549  println(s"[Backend] memExuBlocksHasVecLoad: $memExuBlocksHasVecLoad")
550
551  private val toMem = Wire(bypassNetwork.io.toExus.mem.cloneType)
552  for (i <- toMem.indices) {
553    for (j <- toMem(i).indices) {
554      val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.mem(i)(j).bits.loadDependency, io.mem.ldCancel)
555      val issueTimeout =
556        if (memExuBlocksHasLDU(i)(j))
557          Counter(0 until 16, toMem(i)(j).valid && !toMem(i)(j).fire, bypassNetwork.io.toExus.mem(i)(j).fire)._2
558        else
559          false.B
560
561      if (memScheduler.io.loadFinalIssueResp(i).nonEmpty && memExuBlocksHasLDU(i)(j)) {
562        memScheduler.io.loadFinalIssueResp(i)(j).valid := issueTimeout
563        memScheduler.io.loadFinalIssueResp(i)(j).bits.fuType := toMem(i)(j).bits.fuType
564        memScheduler.io.loadFinalIssueResp(i)(j).bits.resp := RespType.block
565        memScheduler.io.loadFinalIssueResp(i)(j).bits.robIdx := toMem(i)(j).bits.robIdx
566        memScheduler.io.loadFinalIssueResp(i)(j).bits.uopIdx.foreach(_ := toMem(i)(j).bits.vpu.get.vuopIdx)
567        memScheduler.io.loadFinalIssueResp(i)(j).bits.sqIdx.foreach(_ := toMem(i)(j).bits.sqIdx.get)
568        memScheduler.io.loadFinalIssueResp(i)(j).bits.lqIdx.foreach(_ := toMem(i)(j).bits.lqIdx.get)
569      }
570
571      NewPipelineConnect(
572        bypassNetwork.io.toExus.mem(i)(j), toMem(i)(j), toMem(i)(j).fire,
573        Mux(
574          bypassNetwork.io.toExus.mem(i)(j).fire,
575          bypassNetwork.io.toExus.mem(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel,
576          toMem(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || issueTimeout
577        ),
578        Option("bypassNetwork2toMemExus")
579      )
580
581      if (memScheduler.io.memAddrIssueResp(i).nonEmpty && memExuBlocksHasLDU(i)(j)) {
582        memScheduler.io.memAddrIssueResp(i)(j).valid := toMem(i)(j).fire && FuType.isLoad(toMem(i)(j).bits.fuType)
583        memScheduler.io.memAddrIssueResp(i)(j).bits.fuType := toMem(i)(j).bits.fuType
584        memScheduler.io.memAddrIssueResp(i)(j).bits.robIdx := toMem(i)(j).bits.robIdx
585        memScheduler.io.memAddrIssueResp(i)(j).bits.sqIdx.foreach(_ := toMem(i)(j).bits.sqIdx.get)
586        memScheduler.io.memAddrIssueResp(i)(j).bits.lqIdx.foreach(_ := toMem(i)(j).bits.lqIdx.get)
587        memScheduler.io.memAddrIssueResp(i)(j).bits.resp := RespType.success // for load inst, firing at toMem means issuing successfully
588      }
589
590      if (memScheduler.io.vecLoadIssueResp(i).nonEmpty && memExuBlocksHasVecLoad(i)(j)) {
591        memScheduler.io.vecLoadIssueResp(i)(j) match {
592          case resp =>
593            resp.valid := toMem(i)(j).fire && VlduType.isVecLd(toMem(i)(j).bits.fuOpType)
594            resp.bits.fuType := toMem(i)(j).bits.fuType
595            resp.bits.robIdx := toMem(i)(j).bits.robIdx
596            resp.bits.uopIdx.get := toMem(i)(j).bits.vpu.get.vuopIdx
597            resp.bits.sqIdx.get := toMem(i)(j).bits.sqIdx.get
598            resp.bits.lqIdx.get := toMem(i)(j).bits.lqIdx.get
599            resp.bits.resp := RespType.success
600        }
601        if (backendParams.debugEn){
602          dontTouch(memScheduler.io.vecLoadIssueResp(i)(j))
603        }
604      }
605    }
606  }
607
608  io.mem.redirect := ctrlBlock.io.redirect
609  io.mem.issueUops.zip(toMem.flatten).foreach { case (sink, source) =>
610    val enableMdp = Constantin.createRecord("EnableMdp", true)
611    sink.valid := source.valid
612    source.ready := sink.ready
613    sink.bits.iqIdx              := source.bits.iqIdx
614    sink.bits.isFirstIssue       := source.bits.isFirstIssue
615    sink.bits.uop                := 0.U.asTypeOf(sink.bits.uop)
616    sink.bits.src                := 0.U.asTypeOf(sink.bits.src)
617    sink.bits.src.zip(source.bits.src).foreach { case (l, r) => l := r}
618    sink.bits.uop.fuType         := source.bits.fuType
619    sink.bits.uop.fuOpType       := source.bits.fuOpType
620    sink.bits.uop.imm            := source.bits.imm
621    sink.bits.uop.robIdx         := source.bits.robIdx
622    sink.bits.uop.pdest          := source.bits.pdest
623    sink.bits.uop.rfWen          := source.bits.rfWen.getOrElse(false.B)
624    sink.bits.uop.fpWen          := source.bits.fpWen.getOrElse(false.B)
625    sink.bits.uop.vecWen         := source.bits.vecWen.getOrElse(false.B)
626    sink.bits.uop.v0Wen          := source.bits.v0Wen.getOrElse(false.B)
627    sink.bits.uop.vlWen          := source.bits.vlWen.getOrElse(false.B)
628    sink.bits.uop.flushPipe      := source.bits.flushPipe.getOrElse(false.B)
629    sink.bits.uop.pc             := source.bits.pc.getOrElse(0.U)
630    sink.bits.uop.loadWaitBit    := Mux(enableMdp, source.bits.loadWaitBit.getOrElse(false.B), false.B)
631    sink.bits.uop.waitForRobIdx  := Mux(enableMdp, source.bits.waitForRobIdx.getOrElse(0.U.asTypeOf(new RobPtr)), 0.U.asTypeOf(new RobPtr))
632    sink.bits.uop.storeSetHit    := Mux(enableMdp, source.bits.storeSetHit.getOrElse(false.B), false.B)
633    sink.bits.uop.loadWaitStrict := Mux(enableMdp, source.bits.loadWaitStrict.getOrElse(false.B), false.B)
634    sink.bits.uop.ssid           := Mux(enableMdp, source.bits.ssid.getOrElse(0.U(SSIDWidth.W)), 0.U(SSIDWidth.W))
635    sink.bits.uop.lqIdx          := source.bits.lqIdx.getOrElse(0.U.asTypeOf(new LqPtr))
636    sink.bits.uop.sqIdx          := source.bits.sqIdx.getOrElse(0.U.asTypeOf(new SqPtr))
637    sink.bits.uop.ftqPtr         := source.bits.ftqIdx.getOrElse(0.U.asTypeOf(new FtqPtr))
638    sink.bits.uop.ftqOffset      := source.bits.ftqOffset.getOrElse(0.U)
639    sink.bits.uop.debugInfo      := source.bits.perfDebugInfo
640    sink.bits.uop.vpu            := source.bits.vpu.getOrElse(0.U.asTypeOf(new VPUCtrlSignals))
641    sink.bits.uop.preDecodeInfo  := source.bits.preDecode.getOrElse(0.U.asTypeOf(new PreDecodeInfo))
642    sink.bits.uop.numLsElem      := source.bits.numLsElem.getOrElse(0.U) // Todo: remove this bundle, keep only the one below
643    sink.bits.flowNum.foreach(_  := source.bits.numLsElem.get)
644  }
645  io.mem.loadFastMatch := memScheduler.io.toMem.get.loadFastMatch.map(_.fastMatch)
646  io.mem.loadFastImm := memScheduler.io.toMem.get.loadFastMatch.map(_.fastImm)
647  io.mem.tlbCsr := csrio.tlb
648  io.mem.csrCtrl := csrio.customCtrl
649  io.mem.sfence := fenceio.sfence
650  io.mem.isStoreException := CommitType.lsInstIsStore(ctrlBlock.io.robio.exception.bits.commitType)
651  io.mem.isVlsException := ctrlBlock.io.robio.exception.bits.vls
652  require(io.mem.loadPcRead.size == params.LduCnt)
653  io.mem.loadPcRead.zipWithIndex.foreach { case (loadPcRead, i) =>
654    loadPcRead := ctrlBlock.io.memLdPcRead(i).data
655    ctrlBlock.io.memLdPcRead(i).valid := io.mem.issueLda(i).valid
656    ctrlBlock.io.memLdPcRead(i).ptr := io.mem.issueLda(i).bits.uop.ftqPtr
657    ctrlBlock.io.memLdPcRead(i).offset := io.mem.issueLda(i).bits.uop.ftqOffset
658  }
659
660  io.mem.storePcRead.zipWithIndex.foreach { case (storePcRead, i) =>
661    storePcRead := ctrlBlock.io.memStPcRead(i).data
662    ctrlBlock.io.memStPcRead(i).valid := io.mem.issueSta(i).valid
663    ctrlBlock.io.memStPcRead(i).ptr := io.mem.issueSta(i).bits.uop.ftqPtr
664    ctrlBlock.io.memStPcRead(i).offset := io.mem.issueSta(i).bits.uop.ftqOffset
665  }
666
667  io.mem.hyuPcRead.zipWithIndex.foreach( { case (hyuPcRead, i) =>
668    hyuPcRead := ctrlBlock.io.memHyPcRead(i).data
669    ctrlBlock.io.memHyPcRead(i).valid := io.mem.issueHylda(i).valid
670    ctrlBlock.io.memHyPcRead(i).ptr := io.mem.issueHylda(i).bits.uop.ftqPtr
671    ctrlBlock.io.memHyPcRead(i).offset := io.mem.issueHylda(i).bits.uop.ftqOffset
672  })
673
674  ctrlBlock.io.robio.robHeadLsIssue := io.mem.issueUops.map(deq => deq.fire && deq.bits.uop.robIdx === ctrlBlock.io.robio.robDeqPtr).reduce(_ || _)
675
676  // mem io
677  io.mem.lsqEnqIO <> memScheduler.io.memIO.get.lsqEnqIO
678  io.mem.robLsqIO <> ctrlBlock.io.robio.lsq
679
680  io.frontendSfence := fenceio.sfence
681  io.frontendTlbCsr := csrio.tlb
682  io.frontendCsrCtrl := csrio.customCtrl
683
684  io.tlb <> csrio.tlb
685
686  io.csrCustomCtrl := csrio.customCtrl
687
688  io.toTop.cpuHalted := false.B // TODO: implement cpu halt
689
690  io.debugTopDown.fromRob := ctrlBlock.io.debugTopDown.fromRob
691  ctrlBlock.io.debugTopDown.fromCore := io.debugTopDown.fromCore
692
693  io.debugRolling := ctrlBlock.io.debugRolling
694
695  if(backendParams.debugEn) {
696    dontTouch(memScheduler.io)
697    dontTouch(dataPath.io.toMemExu)
698    dontTouch(wbDataPath.io.fromMemExu)
699  }
700
701  // reset tree
702  if (p(DebugOptionsKey).ResetGen) {
703    val rightResetTree = ResetGenNode(Seq(
704      ModuleNode(dataPath),
705      ModuleNode(intExuBlock),
706      ModuleNode(fpExuBlock),
707      ModuleNode(vfExuBlock),
708      ModuleNode(bypassNetwork),
709      ModuleNode(wbDataPath)
710    ))
711    val leftResetTree = ResetGenNode(Seq(
712      ModuleNode(pcTargetMem),
713      ModuleNode(intScheduler),
714      ModuleNode(fpScheduler),
715      ModuleNode(vfScheduler),
716      ModuleNode(memScheduler),
717      ModuleNode(og2ForVector),
718      ModuleNode(wbFuBusyTable),
719      ResetGenNode(Seq(
720        ModuleNode(ctrlBlock),
721        ResetGenNode(Seq(
722          CellNode(io.frontendReset)
723        ))
724      ))
725    ))
726    ResetGen(leftResetTree, reset, sim = false)
727    ResetGen(rightResetTree, reset, sim = false)
728  } else {
729    io.frontendReset := DontCare
730  }
731
732  // perf events
733  val pfevent = Module(new PFEvent)
734  pfevent.io.distribute_csr := RegNext(csrio.customCtrl.distribute_csr)
735  val csrevents = pfevent.io.hpmevent.slice(8,16)
736
737  val ctrlBlockPerf    = ctrlBlock.getPerfEvents
738  val intSchedulerPerf = intScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents
739  val fpSchedulerPerf  = fpScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents
740  val vecSchedulerPerf = vfScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents
741  val memSchedulerPerf = memScheduler.asInstanceOf[SchedulerMemImp].getPerfEvents
742
743  val perfBackend  = Seq()
744  // let index = 0 be no event
745  val allPerfEvents = Seq(("noEvent", 0.U)) ++ ctrlBlockPerf ++ intSchedulerPerf ++ fpSchedulerPerf ++ vecSchedulerPerf ++ memSchedulerPerf ++ perfBackend
746
747
748  if (printEventCoding) {
749    for (((name, inc), i) <- allPerfEvents.zipWithIndex) {
750      println("backend perfEvents Set", name, inc, i)
751    }
752  }
753
754  val allPerfInc = allPerfEvents.map(_._2.asTypeOf(new PerfEvent))
755  val perfEvents = HPerfMonitor(csrevents, allPerfInc).getPerfEvents
756  csrio.perf.perfEventsBackend := VecInit(perfEvents.map(_._2.asTypeOf(new PerfEvent)))
757  generatePerfEvent()
758}
759
760class BackendMemIO(implicit p: Parameters, params: BackendParams) extends XSBundle {
761  // Since fast load replay always use load unit 0, Backend flips two load port to avoid conflicts
762  val flippedLda = true
763  // params alias
764  private val LoadQueueSize = VirtualLoadQueueSize
765  // In/Out // Todo: split it into one-direction bundle
766  val lsqEnqIO = Flipped(new LsqEnqIO)
767  val robLsqIO = new RobLsqIO
768  val ldaIqFeedback = Vec(params.LduCnt, Flipped(new MemRSFeedbackIO))
769  val staIqFeedback = Vec(params.StaCnt, Flipped(new MemRSFeedbackIO))
770  val hyuIqFeedback = Vec(params.HyuCnt, Flipped(new MemRSFeedbackIO))
771  val vstuIqFeedback = Flipped(Vec(params.VstuCnt, new MemRSFeedbackIO(isVector = true)))
772  val vlduIqFeedback = Flipped(Vec(params.VlduCnt, new MemRSFeedbackIO(isVector = true)))
773  val ldCancel = Vec(params.LdExuCnt, Input(new LoadCancelIO))
774  val wakeup = Vec(params.LdExuCnt, Flipped(Valid(new DynInst)))
775  val loadPcRead = Vec(params.LduCnt, Output(UInt(VAddrBits.W)))
776  val storePcRead = Vec(params.StaCnt, Output(UInt(VAddrBits.W)))
777  val hyuPcRead = Vec(params.HyuCnt, Output(UInt(VAddrBits.W)))
778  // Input
779  val writebackLda = Vec(params.LduCnt, Flipped(DecoupledIO(new MemExuOutput)))
780  val writebackSta = Vec(params.StaCnt, Flipped(DecoupledIO(new MemExuOutput)))
781  val writebackStd = Vec(params.StdCnt, Flipped(DecoupledIO(new MemExuOutput)))
782  val writebackHyuLda = Vec(params.HyuCnt, Flipped(DecoupledIO(new MemExuOutput)))
783  val writebackHyuSta = Vec(params.HyuCnt, Flipped(DecoupledIO(new MemExuOutput)))
784  val writebackVldu = Vec(params.VlduCnt, Flipped(DecoupledIO(new MemExuOutput(true))))
785
786  val s3_delayed_load_error = Input(Vec(LoadPipelineWidth, Bool()))
787  val stIn = Input(Vec(params.StaExuCnt, ValidIO(new DynInst())))
788  val memoryViolation = Flipped(ValidIO(new Redirect))
789  val exceptionAddr = Input(new Bundle {
790    val vaddr = UInt(VAddrBits.W)
791    val gpaddr = UInt(GPAddrBits.W)
792  })
793  val sqDeq = Input(UInt(log2Ceil(EnsbufferWidth + 1).W))
794  val lqDeq = Input(UInt(log2Up(CommitWidth + 1).W))
795  val sqDeqPtr = Input(new SqPtr)
796  val lqDeqPtr = Input(new LqPtr)
797
798  val lqCancelCnt = Input(UInt(log2Up(VirtualLoadQueueSize + 1).W))
799  val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W))
800
801  val lqCanAccept = Input(Bool())
802  val sqCanAccept = Input(Bool())
803
804  val otherFastWakeup = Flipped(Vec(params.LduCnt + params.HyuCnt, ValidIO(new DynInst)))
805  val stIssuePtr = Input(new SqPtr())
806
807  val debugLS = Flipped(Output(new DebugLSIO))
808
809  val lsTopdownInfo = Vec(params.LduCnt + params.HyuCnt, Flipped(Output(new LsTopdownInfo)))
810  // Output
811  val redirect = ValidIO(new Redirect)   // rob flush MemBlock
812  val issueLda = MixedVec(Seq.fill(params.LduCnt)(DecoupledIO(new MemExuInput())))
813  val issueSta = MixedVec(Seq.fill(params.StaCnt)(DecoupledIO(new MemExuInput())))
814  val issueStd = MixedVec(Seq.fill(params.StdCnt)(DecoupledIO(new MemExuInput())))
815  val issueHylda = MixedVec(Seq.fill(params.HyuCnt)(DecoupledIO(new MemExuInput())))
816  val issueHysta = MixedVec(Seq.fill(params.HyuCnt)(DecoupledIO(new MemExuInput())))
817  val issueVldu = MixedVec(Seq.fill(params.VlduCnt)(DecoupledIO(new MemExuInput(true))))
818
819  val loadFastMatch = Vec(params.LduCnt, Output(UInt(params.LduCnt.W)))
820  val loadFastImm   = Vec(params.LduCnt, Output(UInt(12.W))) // Imm_I
821
822  val tlbCsr = Output(new TlbCsrBundle)
823  val csrCtrl = Output(new CustomCSRCtrlIO)
824  val sfence = Output(new SfenceBundle)
825  val isStoreException = Output(Bool())
826  val isVlsException = Output(Bool())
827
828  // ATTENTION: The issue ports' sequence order should be the same as IQs' deq config
829  private [backend] def issueUops: Seq[DecoupledIO[MemExuInput]] = {
830    issueSta ++
831      issueHylda ++ issueHysta ++
832      issueLda ++
833      issueVldu ++
834      issueStd
835  }.toSeq
836
837  // ATTENTION: The writeback ports' sequence order should be the same as IQs' deq config
838  private [backend] def writeBack: Seq[DecoupledIO[MemExuOutput]] = {
839    writebackSta ++
840      writebackHyuLda ++ writebackHyuSta ++
841      writebackLda ++
842      writebackVldu ++
843      writebackStd
844  }
845}
846
847class TopToBackendBundle(implicit p: Parameters) extends XSBundle {
848  val hartId            = Output(UInt(hartIdLen.W))
849  val externalInterrupt = Output(new ExternalInterruptIO)
850  val msiInfo           = Output(ValidIO(new MsiInfoBundle))
851  val clintTime         = Output(ValidIO(UInt(64.W)))
852}
853
854class BackendToTopBundle extends Bundle {
855  val cpuHalted = Output(Bool())
856}
857
858class BackendIO(implicit p: Parameters, params: BackendParams) extends XSBundle with HasSoCParameter {
859  val fromTop = Flipped(new TopToBackendBundle)
860
861  val toTop = new BackendToTopBundle
862
863  val fenceio = new FenceIO
864  // Todo: merge these bundles into BackendFrontendIO
865  val frontend = Flipped(new FrontendToCtrlIO)
866  val frontendSfence = Output(new SfenceBundle)
867  val frontendCsrCtrl = Output(new CustomCSRCtrlIO)
868  val frontendTlbCsr = Output(new TlbCsrBundle)
869  val frontendReset = Output(Reset())
870
871  val mem = new BackendMemIO
872
873  val perf = Input(new PerfCounterIO)
874
875  val tlb = Output(new TlbCsrBundle)
876
877  val csrCustomCtrl = Output(new CustomCSRCtrlIO)
878
879  val debugTopDown = new Bundle {
880    val fromRob = new RobCoreTopDownIO
881    val fromCore = new CoreDispatchTopDownIO
882  }
883  val debugRolling = new RobDebugRollingIO
884}
885