xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision fa16cf81edffdc820ae5a44287acc5fb650e763d)
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.trapInst <> intExuBlock.io.csrio.get.trapInst
228  ctrlBlock.io.robio.csr.intrBitSet := intExuBlock.io.csrio.get.interrupt
229  ctrlBlock.io.robio.csr.trapTarget := intExuBlock.io.csrio.get.trapTarget
230  ctrlBlock.io.robio.csr.isXRet := intExuBlock.io.csrio.get.isXRet
231  ctrlBlock.io.robio.csr.wfiEvent := intExuBlock.io.csrio.get.wfi_event
232  ctrlBlock.io.robio.lsq <> io.mem.robLsqIO
233  ctrlBlock.io.robio.lsTopdownInfo <> io.mem.lsTopdownInfo
234  ctrlBlock.io.robio.debug_ls <> io.mem.debugLS
235  ctrlBlock.io.debugEnqLsq.canAccept := io.mem.lsqEnqIO.canAccept
236  ctrlBlock.io.debugEnqLsq.resp := io.mem.lsqEnqIO.resp
237  ctrlBlock.io.debugEnqLsq.req := memScheduler.io.memIO.get.lsqEnqIO.req
238  ctrlBlock.io.debugEnqLsq.needAlloc := memScheduler.io.memIO.get.lsqEnqIO.needAlloc
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
312  vfScheduler.io.fromTop.hartId := io.fromTop.hartId
313  vfScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush
314  vfScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs
315  vfScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.vfUops
316  vfScheduler.io.intWriteBack := 0.U.asTypeOf(vfScheduler.io.intWriteBack)
317  vfScheduler.io.fpWriteBack := 0.U.asTypeOf(vfScheduler.io.fpWriteBack)
318  vfScheduler.io.vfWriteBack := wbDataPath.io.toVfPreg
319  vfScheduler.io.v0WriteBack := wbDataPath.io.toV0Preg
320  vfScheduler.io.vlWriteBack := wbDataPath.io.toVlPreg
321  vfScheduler.io.fromDataPath.resp := dataPath.io.toVfIQ
322  vfScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) }
323  vfScheduler.io.fromDataPath.og0Cancel := og0Cancel
324  vfScheduler.io.fromDataPath.og1Cancel := og1Cancel
325  vfScheduler.io.ldCancel := io.mem.ldCancel
326  vfScheduler.io.vlWriteBackInfo.vlIsZero := vlIsZero
327  vfScheduler.io.vlWriteBackInfo.vlIsVlmax := vlIsVlmax
328  vfScheduler.io.fromOg2.get := og2ForVector.io.toVfIQ
329
330  dataPath.io.hartId := io.fromTop.hartId
331  dataPath.io.flush := ctrlBlock.io.toDataPath.flush
332
333  dataPath.io.fromIntIQ <> intScheduler.io.toDataPathAfterDelay
334  dataPath.io.fromFpIQ <> fpScheduler.io.toDataPathAfterDelay
335  dataPath.io.fromVfIQ <> vfScheduler.io.toDataPathAfterDelay
336  dataPath.io.fromMemIQ <> memScheduler.io.toDataPathAfterDelay
337
338  dataPath.io.ldCancel := io.mem.ldCancel
339
340  println(s"[Backend] wbDataPath.io.toIntPreg: ${wbDataPath.io.toIntPreg.size}, dataPath.io.fromIntWb: ${dataPath.io.fromIntWb.size}")
341  println(s"[Backend] wbDataPath.io.toVfPreg: ${wbDataPath.io.toVfPreg.size}, dataPath.io.fromFpWb: ${dataPath.io.fromVfWb.size}")
342  dataPath.io.fromIntWb := wbDataPath.io.toIntPreg
343  dataPath.io.fromFpWb := wbDataPath.io.toFpPreg
344  dataPath.io.fromVfWb := wbDataPath.io.toVfPreg
345  dataPath.io.fromV0Wb := wbDataPath.io.toV0Preg
346  dataPath.io.fromVlWb := wbDataPath.io.toVlPreg
347  dataPath.io.debugIntRat    .foreach(_ := ctrlBlock.io.debug_int_rat.get)
348  dataPath.io.debugFpRat     .foreach(_ := ctrlBlock.io.debug_fp_rat.get)
349  dataPath.io.debugVecRat    .foreach(_ := ctrlBlock.io.debug_vec_rat.get)
350  dataPath.io.debugV0Rat     .foreach(_ := ctrlBlock.io.debug_v0_rat.get)
351  dataPath.io.debugVlRat     .foreach(_ := ctrlBlock.io.debug_vl_rat.get)
352  dataPath.io.fromBypassNetwork := bypassNetwork.io.toDataPath
353
354  og2ForVector.io.flush := ctrlBlock.io.toDataPath.flush
355  og2ForVector.io.ldCancel := io.mem.ldCancel
356  og2ForVector.io.fromOg1NoReg <> dataPath.io.toVecExu
357  og2ForVector.io.fromOg1ImmInfo := dataPath.io.og1ImmInfo.zip(params.allExuParams).filter(_._2.isVfExeUnit).map(_._1)
358
359  bypassNetwork.io.fromDataPath.int <> dataPath.io.toIntExu
360  bypassNetwork.io.fromDataPath.fp <> dataPath.io.toFpExu
361  bypassNetwork.io.fromDataPath.vf <> og2ForVector.io.toVfExu
362  bypassNetwork.io.fromDataPath.mem <> dataPath.io.toMemExu
363  bypassNetwork.io.fromDataPath.immInfo := dataPath.io.og1ImmInfo
364  bypassNetwork.io.fromDataPath.immInfo.zip(params.allExuParams).filter(_._2.isVfExeUnit).map(_._1).zip(og2ForVector.io.toVfImmInfo).map{
365    case (vfImmInfo, og2ImmInfo) => vfImmInfo := og2ImmInfo
366  }
367  bypassNetwork.io.fromDataPath.rcData := dataPath.io.toBypassNetworkRCData
368  bypassNetwork.io.fromExus.connectExuOutput(_.int)(intExuBlock.io.out)
369  bypassNetwork.io.fromExus.connectExuOutput(_.fp)(fpExuBlock.io.out)
370  bypassNetwork.io.fromExus.connectExuOutput(_.vf)(vfExuBlock.io.out)
371
372  require(bypassNetwork.io.fromExus.mem.flatten.size == io.mem.writeBack.size,
373    s"bypassNetwork.io.fromExus.mem.flatten.size(${bypassNetwork.io.fromExus.mem.flatten.size}: ${bypassNetwork.io.fromExus.mem.map(_.size)}, " +
374    s"io.mem.writeback(${io.mem.writeBack.size})"
375  )
376  bypassNetwork.io.fromExus.mem.flatten.zip(io.mem.writeBack).foreach { case (sink, source) =>
377    sink.valid := source.valid
378    sink.bits.intWen := source.bits.uop.rfWen && FuType.isLoad(source.bits.uop.fuType)
379    sink.bits.pdest := source.bits.uop.pdest
380    sink.bits.data := source.bits.data
381  }
382
383
384  intExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush
385  for (i <- 0 until intExuBlock.io.in.length) {
386    for (j <- 0 until intExuBlock.io.in(i).length) {
387      val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.int(i)(j).bits.loadDependency, io.mem.ldCancel)
388      NewPipelineConnect(
389        bypassNetwork.io.toExus.int(i)(j), intExuBlock.io.in(i)(j), intExuBlock.io.in(i)(j).fire,
390        Mux(
391          bypassNetwork.io.toExus.int(i)(j).fire,
392          bypassNetwork.io.toExus.int(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel,
393          intExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush)
394        ),
395        Option("bypassNetwork2intExuBlock")
396      )
397    }
398  }
399
400  pcTargetMem.io.fromFrontendFtq := io.frontend.fromFtq
401  pcTargetMem.io.toDataPath <> dataPath.io.fromPcTargetMem
402
403  private val csrin = intExuBlock.io.csrin.get
404  csrin.hartId := io.fromTop.hartId
405  csrin.msiInfo.valid := RegNext(io.fromTop.msiInfo.valid)
406  csrin.msiInfo.bits := RegEnable(io.fromTop.msiInfo.bits, io.fromTop.msiInfo.valid)
407  csrin.clintTime.valid := RegNext(io.fromTop.clintTime.valid)
408  csrin.clintTime.bits := RegEnable(io.fromTop.clintTime.bits, io.fromTop.clintTime.valid)
409
410  private val csrio = intExuBlock.io.csrio.get
411  csrio.hartId := io.fromTop.hartId
412  csrio.fpu.fflags := ctrlBlock.io.robio.csr.fflags
413  csrio.fpu.isIllegal := false.B // Todo: remove it
414  csrio.fpu.dirty_fs := ctrlBlock.io.robio.csr.dirty_fs
415  csrio.vpu <> WireDefault(0.U.asTypeOf(csrio.vpu)) // Todo
416
417  val fromIntExuVsetVType = intExuBlock.io.vtype.getOrElse(0.U.asTypeOf((Valid(new VType))))
418  val fromVfExuVsetVType = vfExuBlock.io.vtype.getOrElse(0.U.asTypeOf((Valid(new VType))))
419  val fromVsetVType = Mux(fromIntExuVsetVType.valid, fromIntExuVsetVType.bits, fromVfExuVsetVType.bits)
420  val vsetvlVType = RegEnable(fromVsetVType, 0.U.asTypeOf(new VType), fromIntExuVsetVType.valid || fromVfExuVsetVType.valid)
421  ctrlBlock.io.toDecode.vsetvlVType := vsetvlVType
422
423  val commitVType = ctrlBlock.io.robio.commitVType.vtype
424  val hasVsetvl = ctrlBlock.io.robio.commitVType.hasVsetvl
425  val vtype = VType.toVtypeStruct(Mux(hasVsetvl, vsetvlVType, commitVType.bits)).asUInt
426
427  // csr not store the value of vl, so when using difftest we assign the value of vl to debugVl
428  val debugVl_s0 = WireInit(UInt(VlData().dataWidth.W), 0.U)
429  val debugVl_s1 = WireInit(UInt(VlData().dataWidth.W), 0.U)
430  debugVl_s0 := dataPath.io.debugVl.getOrElse(0.U.asTypeOf(UInt(VlData().dataWidth.W)))
431  debugVl_s1 := RegNext(debugVl_s0)
432  csrio.vpu.set_vxsat := ctrlBlock.io.robio.csr.vxsat
433  csrio.vpu.set_vstart.valid := ctrlBlock.io.robio.csr.vstart.valid
434  csrio.vpu.set_vstart.bits := ctrlBlock.io.robio.csr.vstart.bits
435  ctrlBlock.io.toDecode.vstart := csrio.vpu.vstart
436  //Todo here need change design
437  csrio.vpu.set_vtype.valid := commitVType.valid
438  csrio.vpu.set_vtype.bits := ZeroExt(vtype, XLEN)
439  csrio.vpu.vl := ZeroExt(debugVl_s1, XLEN)
440  csrio.vpu.dirty_vs := ctrlBlock.io.robio.csr.dirty_vs
441  csrio.exception := ctrlBlock.io.robio.exception
442  csrio.memExceptionVAddr := io.mem.exceptionAddr.vaddr
443  csrio.memExceptionGPAddr := io.mem.exceptionAddr.gpaddr
444  csrio.externalInterrupt := RegNext(io.fromTop.externalInterrupt)
445  csrio.perf <> io.perf
446  csrio.perf.retiredInstr <> ctrlBlock.io.robio.csr.perfinfo.retiredInstr
447  csrio.perf.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo
448  private val fenceio = intExuBlock.io.fenceio.get
449  io.fenceio <> fenceio
450
451  // to fpExuBlock
452  fpExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush
453  for (i <- 0 until fpExuBlock.io.in.length) {
454    for (j <- 0 until fpExuBlock.io.in(i).length) {
455      val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.fp(i)(j).bits.loadDependency, io.mem.ldCancel)
456      NewPipelineConnect(
457        bypassNetwork.io.toExus.fp(i)(j), fpExuBlock.io.in(i)(j), fpExuBlock.io.in(i)(j).fire,
458        Mux(
459          bypassNetwork.io.toExus.fp(i)(j).fire,
460          bypassNetwork.io.toExus.fp(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel,
461          fpExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush)
462        ),
463        Option("bypassNetwork2fpExuBlock")
464      )
465    }
466  }
467
468  vfExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush
469  for (i <- 0 until vfExuBlock.io.in.size) {
470    for (j <- 0 until vfExuBlock.io.in(i).size) {
471      val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.vf(i)(j).bits.loadDependency, io.mem.ldCancel)
472      NewPipelineConnect(
473        bypassNetwork.io.toExus.vf(i)(j), vfExuBlock.io.in(i)(j), vfExuBlock.io.in(i)(j).fire,
474        Mux(
475          bypassNetwork.io.toExus.vf(i)(j).fire,
476          bypassNetwork.io.toExus.vf(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel,
477          vfExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush)
478        ),
479        Option("bypassNetwork2vfExuBlock")
480      )
481
482    }
483  }
484
485  intExuBlock.io.frm.foreach(_ := csrio.fpu.frm)
486  fpExuBlock.io.frm.foreach(_ := csrio.fpu.frm)
487  fpExuBlock.io.vxrm.foreach(_ := csrio.vpu.vxrm)
488  vfExuBlock.io.frm.foreach(_ := csrio.fpu.frm)
489  vfExuBlock.io.vxrm.foreach(_ := csrio.vpu.vxrm)
490
491  wbDataPath.io.flush := ctrlBlock.io.redirect
492  wbDataPath.io.fromTop.hartId := io.fromTop.hartId
493  wbDataPath.io.fromIntExu <> intExuBlock.io.out
494  wbDataPath.io.fromFpExu <> fpExuBlock.io.out
495  wbDataPath.io.fromVfExu <> vfExuBlock.io.out
496  wbDataPath.io.fromMemExu.flatten.zip(io.mem.writeBack).foreach { case (sink, source) =>
497    sink.valid := source.valid
498    source.ready := sink.ready
499    sink.bits.data   := VecInit(Seq.fill(sink.bits.params.wbPathNum)(source.bits.data))
500    sink.bits.pdest  := source.bits.uop.pdest
501    sink.bits.robIdx := source.bits.uop.robIdx
502    sink.bits.intWen.foreach(_ := source.bits.uop.rfWen)
503    sink.bits.fpWen.foreach(_ := source.bits.uop.fpWen)
504    sink.bits.vecWen.foreach(_ := source.bits.uop.vecWen)
505    sink.bits.v0Wen.foreach(_ := source.bits.uop.v0Wen)
506    sink.bits.vlWen.foreach(_ := source.bits.uop.vlWen)
507    sink.bits.exceptionVec.foreach(_ := source.bits.uop.exceptionVec)
508    sink.bits.flushPipe.foreach(_ := source.bits.uop.flushPipe)
509    sink.bits.replay.foreach(_ := source.bits.uop.replayInst)
510    sink.bits.debug := source.bits.debug
511    sink.bits.debugInfo := source.bits.uop.debugInfo
512    sink.bits.lqIdx.foreach(_ := source.bits.uop.lqIdx)
513    sink.bits.sqIdx.foreach(_ := source.bits.uop.sqIdx)
514    sink.bits.predecodeInfo.foreach(_ := source.bits.uop.preDecodeInfo)
515    sink.bits.vls.foreach(x => {
516      x.vdIdx := source.bits.vdIdx.get
517      x.vdIdxInField := source.bits.vdIdxInField.get
518      x.vpu   := source.bits.uop.vpu
519      x.oldVdPsrc := source.bits.uop.psrc(2)
520      x.isIndexed := VlduType.isIndexed(source.bits.uop.fuOpType)
521      x.isMasked := VlduType.isMasked(source.bits.uop.fuOpType)
522    })
523    sink.bits.trigger.foreach(_ := source.bits.uop.trigger)
524  }
525
526  // to mem
527  private val memIssueParams = params.memSchdParams.get.issueBlockParams
528  private val memExuBlocksHasLDU = memIssueParams.map(_.exuBlockParams.map(x => x.hasLoadFu || x.hasHyldaFu))
529  private val memExuBlocksHasVecLoad = memIssueParams.map(_.exuBlockParams.map(x => x.hasVLoadFu))
530  println(s"[Backend] memExuBlocksHasLDU: $memExuBlocksHasLDU")
531  println(s"[Backend] memExuBlocksHasVecLoad: $memExuBlocksHasVecLoad")
532
533  private val toMem = Wire(bypassNetwork.io.toExus.mem.cloneType)
534  for (i <- toMem.indices) {
535    for (j <- toMem(i).indices) {
536      val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.mem(i)(j).bits.loadDependency, io.mem.ldCancel)
537      val issueTimeout =
538        if (memExuBlocksHasLDU(i)(j))
539          Counter(0 until 16, toMem(i)(j).valid && !toMem(i)(j).fire, bypassNetwork.io.toExus.mem(i)(j).fire)._2
540        else
541          false.B
542
543      if (memScheduler.io.loadFinalIssueResp(i).nonEmpty && memExuBlocksHasLDU(i)(j)) {
544        memScheduler.io.loadFinalIssueResp(i)(j).valid := issueTimeout
545        memScheduler.io.loadFinalIssueResp(i)(j).bits.fuType := toMem(i)(j).bits.fuType
546        memScheduler.io.loadFinalIssueResp(i)(j).bits.resp := RespType.block
547        memScheduler.io.loadFinalIssueResp(i)(j).bits.robIdx := toMem(i)(j).bits.robIdx
548        memScheduler.io.loadFinalIssueResp(i)(j).bits.uopIdx.foreach(_ := toMem(i)(j).bits.vpu.get.vuopIdx)
549        memScheduler.io.loadFinalIssueResp(i)(j).bits.sqIdx.foreach(_ := toMem(i)(j).bits.sqIdx.get)
550        memScheduler.io.loadFinalIssueResp(i)(j).bits.lqIdx.foreach(_ := toMem(i)(j).bits.lqIdx.get)
551      }
552
553      NewPipelineConnect(
554        bypassNetwork.io.toExus.mem(i)(j), toMem(i)(j), toMem(i)(j).fire,
555        Mux(
556          bypassNetwork.io.toExus.mem(i)(j).fire,
557          bypassNetwork.io.toExus.mem(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel,
558          toMem(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || issueTimeout
559        ),
560        Option("bypassNetwork2toMemExus")
561      )
562
563      if (memScheduler.io.memAddrIssueResp(i).nonEmpty && memExuBlocksHasLDU(i)(j)) {
564        memScheduler.io.memAddrIssueResp(i)(j).valid := toMem(i)(j).fire && FuType.isLoad(toMem(i)(j).bits.fuType)
565        memScheduler.io.memAddrIssueResp(i)(j).bits.fuType := toMem(i)(j).bits.fuType
566        memScheduler.io.memAddrIssueResp(i)(j).bits.robIdx := toMem(i)(j).bits.robIdx
567        memScheduler.io.memAddrIssueResp(i)(j).bits.sqIdx.foreach(_ := toMem(i)(j).bits.sqIdx.get)
568        memScheduler.io.memAddrIssueResp(i)(j).bits.lqIdx.foreach(_ := toMem(i)(j).bits.lqIdx.get)
569        memScheduler.io.memAddrIssueResp(i)(j).bits.resp := RespType.success // for load inst, firing at toMem means issuing successfully
570      }
571
572      if (memScheduler.io.vecLoadIssueResp(i).nonEmpty && memExuBlocksHasVecLoad(i)(j)) {
573        memScheduler.io.vecLoadIssueResp(i)(j) match {
574          case resp =>
575            resp.valid := toMem(i)(j).fire && VlduType.isVecLd(toMem(i)(j).bits.fuOpType)
576            resp.bits.fuType := toMem(i)(j).bits.fuType
577            resp.bits.robIdx := toMem(i)(j).bits.robIdx
578            resp.bits.uopIdx.get := toMem(i)(j).bits.vpu.get.vuopIdx
579            resp.bits.sqIdx.get := toMem(i)(j).bits.sqIdx.get
580            resp.bits.lqIdx.get := toMem(i)(j).bits.lqIdx.get
581            resp.bits.resp := RespType.success
582        }
583        if (backendParams.debugEn){
584          dontTouch(memScheduler.io.vecLoadIssueResp(i)(j))
585        }
586      }
587    }
588  }
589
590  io.mem.redirect := ctrlBlock.io.redirect
591  io.mem.issueUops.zip(toMem.flatten).foreach { case (sink, source) =>
592    val enableMdp = Constantin.createRecord("EnableMdp", true)
593    sink.valid := source.valid
594    source.ready := sink.ready
595    sink.bits.iqIdx              := source.bits.iqIdx
596    sink.bits.isFirstIssue       := source.bits.isFirstIssue
597    sink.bits.uop                := 0.U.asTypeOf(sink.bits.uop)
598    sink.bits.src                := 0.U.asTypeOf(sink.bits.src)
599    sink.bits.src.zip(source.bits.src).foreach { case (l, r) => l := r}
600    sink.bits.uop.fuType         := source.bits.fuType
601    sink.bits.uop.fuOpType       := source.bits.fuOpType
602    sink.bits.uop.imm            := source.bits.imm
603    sink.bits.uop.robIdx         := source.bits.robIdx
604    sink.bits.uop.pdest          := source.bits.pdest
605    sink.bits.uop.rfWen          := source.bits.rfWen.getOrElse(false.B)
606    sink.bits.uop.fpWen          := source.bits.fpWen.getOrElse(false.B)
607    sink.bits.uop.vecWen         := source.bits.vecWen.getOrElse(false.B)
608    sink.bits.uop.v0Wen          := source.bits.v0Wen.getOrElse(false.B)
609    sink.bits.uop.vlWen          := source.bits.vlWen.getOrElse(false.B)
610    sink.bits.uop.flushPipe      := source.bits.flushPipe.getOrElse(false.B)
611    sink.bits.uop.pc             := source.bits.pc.getOrElse(0.U)
612    sink.bits.uop.loadWaitBit    := Mux(enableMdp, source.bits.loadWaitBit.getOrElse(false.B), false.B)
613    sink.bits.uop.waitForRobIdx  := Mux(enableMdp, source.bits.waitForRobIdx.getOrElse(0.U.asTypeOf(new RobPtr)), 0.U.asTypeOf(new RobPtr))
614    sink.bits.uop.storeSetHit    := Mux(enableMdp, source.bits.storeSetHit.getOrElse(false.B), false.B)
615    sink.bits.uop.loadWaitStrict := Mux(enableMdp, source.bits.loadWaitStrict.getOrElse(false.B), false.B)
616    sink.bits.uop.ssid           := Mux(enableMdp, source.bits.ssid.getOrElse(0.U(SSIDWidth.W)), 0.U(SSIDWidth.W))
617    sink.bits.uop.lqIdx          := source.bits.lqIdx.getOrElse(0.U.asTypeOf(new LqPtr))
618    sink.bits.uop.sqIdx          := source.bits.sqIdx.getOrElse(0.U.asTypeOf(new SqPtr))
619    sink.bits.uop.ftqPtr         := source.bits.ftqIdx.getOrElse(0.U.asTypeOf(new FtqPtr))
620    sink.bits.uop.ftqOffset      := source.bits.ftqOffset.getOrElse(0.U)
621    sink.bits.uop.debugInfo      := source.bits.perfDebugInfo
622    sink.bits.uop.vpu            := source.bits.vpu.getOrElse(0.U.asTypeOf(new VPUCtrlSignals))
623    sink.bits.uop.preDecodeInfo  := source.bits.preDecode.getOrElse(0.U.asTypeOf(new PreDecodeInfo))
624    sink.bits.uop.numLsElem      := source.bits.numLsElem.getOrElse(0.U) // Todo: remove this bundle, keep only the one below
625    sink.bits.flowNum.foreach(_  := source.bits.numLsElem.get)
626  }
627  io.mem.loadFastMatch := memScheduler.io.toMem.get.loadFastMatch.map(_.fastMatch)
628  io.mem.loadFastImm := memScheduler.io.toMem.get.loadFastMatch.map(_.fastImm)
629  io.mem.tlbCsr := csrio.tlb
630  io.mem.csrCtrl := csrio.customCtrl
631  io.mem.sfence := fenceio.sfence
632  io.mem.isStoreException := CommitType.lsInstIsStore(ctrlBlock.io.robio.exception.bits.commitType)
633  io.mem.isVlsException := ctrlBlock.io.robio.exception.bits.vls
634  require(io.mem.loadPcRead.size == params.LduCnt)
635  io.mem.loadPcRead.zipWithIndex.foreach { case (loadPcRead, i) =>
636    loadPcRead := ctrlBlock.io.memLdPcRead(i).data
637    ctrlBlock.io.memLdPcRead(i).valid := io.mem.issueLda(i).valid
638    ctrlBlock.io.memLdPcRead(i).ptr := io.mem.issueLda(i).bits.uop.ftqPtr
639    ctrlBlock.io.memLdPcRead(i).offset := io.mem.issueLda(i).bits.uop.ftqOffset
640  }
641
642  io.mem.storePcRead.zipWithIndex.foreach { case (storePcRead, i) =>
643    storePcRead := ctrlBlock.io.memStPcRead(i).data
644    ctrlBlock.io.memStPcRead(i).valid := io.mem.issueSta(i).valid
645    ctrlBlock.io.memStPcRead(i).ptr := io.mem.issueSta(i).bits.uop.ftqPtr
646    ctrlBlock.io.memStPcRead(i).offset := io.mem.issueSta(i).bits.uop.ftqOffset
647  }
648
649  io.mem.hyuPcRead.zipWithIndex.foreach( { case (hyuPcRead, i) =>
650    hyuPcRead := ctrlBlock.io.memHyPcRead(i).data
651    ctrlBlock.io.memHyPcRead(i).valid := io.mem.issueHylda(i).valid
652    ctrlBlock.io.memHyPcRead(i).ptr := io.mem.issueHylda(i).bits.uop.ftqPtr
653    ctrlBlock.io.memHyPcRead(i).offset := io.mem.issueHylda(i).bits.uop.ftqOffset
654  })
655
656  ctrlBlock.io.robio.robHeadLsIssue := io.mem.issueUops.map(deq => deq.fire && deq.bits.uop.robIdx === ctrlBlock.io.robio.robDeqPtr).reduce(_ || _)
657
658  // mem io
659  io.mem.lsqEnqIO <> memScheduler.io.memIO.get.lsqEnqIO
660  io.mem.robLsqIO <> ctrlBlock.io.robio.lsq
661
662  io.frontendSfence := fenceio.sfence
663  io.frontendTlbCsr := csrio.tlb
664  io.frontendCsrCtrl := csrio.customCtrl
665
666  io.tlb <> csrio.tlb
667
668  io.csrCustomCtrl := csrio.customCtrl
669
670  io.toTop.cpuHalted := false.B // TODO: implement cpu halt
671
672  io.debugTopDown.fromRob := ctrlBlock.io.debugTopDown.fromRob
673  ctrlBlock.io.debugTopDown.fromCore := io.debugTopDown.fromCore
674
675  io.debugRolling := ctrlBlock.io.debugRolling
676
677  if(backendParams.debugEn) {
678    dontTouch(memScheduler.io)
679    dontTouch(dataPath.io.toMemExu)
680    dontTouch(wbDataPath.io.fromMemExu)
681  }
682
683  // reset tree
684  if (p(DebugOptionsKey).ResetGen) {
685    val rightResetTree = ResetGenNode(Seq(
686      ModuleNode(dataPath),
687      ModuleNode(intExuBlock),
688      ModuleNode(fpExuBlock),
689      ModuleNode(vfExuBlock),
690      ModuleNode(bypassNetwork),
691      ModuleNode(wbDataPath)
692    ))
693    val leftResetTree = ResetGenNode(Seq(
694      ModuleNode(pcTargetMem),
695      ModuleNode(intScheduler),
696      ModuleNode(fpScheduler),
697      ModuleNode(vfScheduler),
698      ModuleNode(memScheduler),
699      ModuleNode(og2ForVector),
700      ModuleNode(wbFuBusyTable),
701      ResetGenNode(Seq(
702        ModuleNode(ctrlBlock),
703        ResetGenNode(Seq(
704          CellNode(io.frontendReset)
705        ))
706      ))
707    ))
708    ResetGen(leftResetTree, reset, sim = false)
709    ResetGen(rightResetTree, reset, sim = false)
710  } else {
711    io.frontendReset := DontCare
712  }
713
714  // perf events
715  val pfevent = Module(new PFEvent)
716  pfevent.io.distribute_csr := RegNext(csrio.customCtrl.distribute_csr)
717  val csrevents = pfevent.io.hpmevent.slice(8,16)
718
719  val ctrlBlockPerf    = ctrlBlock.getPerfEvents
720  val intSchedulerPerf = intScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents
721  val fpSchedulerPerf  = fpScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents
722  val vecSchedulerPerf = vfScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents
723  val memSchedulerPerf = memScheduler.asInstanceOf[SchedulerMemImp].getPerfEvents
724
725  val perfBackend  = Seq()
726  // let index = 0 be no event
727  val allPerfEvents = Seq(("noEvent", 0.U)) ++ ctrlBlockPerf ++ intSchedulerPerf ++ fpSchedulerPerf ++ vecSchedulerPerf ++ memSchedulerPerf ++ perfBackend
728
729
730  if (printEventCoding) {
731    for (((name, inc), i) <- allPerfEvents.zipWithIndex) {
732      println("backend perfEvents Set", name, inc, i)
733    }
734  }
735
736  val allPerfInc = allPerfEvents.map(_._2.asTypeOf(new PerfEvent))
737  val perfEvents = HPerfMonitor(csrevents, allPerfInc).getPerfEvents
738  csrio.perf.perfEventsBackend := VecInit(perfEvents.map(_._2.asTypeOf(new PerfEvent)))
739  generatePerfEvent()
740}
741
742class BackendMemIO(implicit p: Parameters, params: BackendParams) extends XSBundle {
743  // Since fast load replay always use load unit 0, Backend flips two load port to avoid conflicts
744  val flippedLda = true
745  // params alias
746  private val LoadQueueSize = VirtualLoadQueueSize
747  // In/Out // Todo: split it into one-direction bundle
748  val lsqEnqIO = Flipped(new LsqEnqIO)
749  val robLsqIO = new RobLsqIO
750  val ldaIqFeedback = Vec(params.LduCnt, Flipped(new MemRSFeedbackIO))
751  val staIqFeedback = Vec(params.StaCnt, Flipped(new MemRSFeedbackIO))
752  val hyuIqFeedback = Vec(params.HyuCnt, Flipped(new MemRSFeedbackIO))
753  val vstuIqFeedback = Flipped(Vec(params.VstuCnt, new MemRSFeedbackIO(isVector = true)))
754  val vlduIqFeedback = Flipped(Vec(params.VlduCnt, new MemRSFeedbackIO(isVector = true)))
755  val ldCancel = Vec(params.LdExuCnt, Input(new LoadCancelIO))
756  val wakeup = Vec(params.LdExuCnt, Flipped(Valid(new DynInst)))
757  val loadPcRead = Vec(params.LduCnt, Output(UInt(VAddrBits.W)))
758  val storePcRead = Vec(params.StaCnt, Output(UInt(VAddrBits.W)))
759  val hyuPcRead = Vec(params.HyuCnt, Output(UInt(VAddrBits.W)))
760  // Input
761  val writebackLda = Vec(params.LduCnt, Flipped(DecoupledIO(new MemExuOutput)))
762  val writebackSta = Vec(params.StaCnt, Flipped(DecoupledIO(new MemExuOutput)))
763  val writebackStd = Vec(params.StdCnt, Flipped(DecoupledIO(new MemExuOutput)))
764  val writebackHyuLda = Vec(params.HyuCnt, Flipped(DecoupledIO(new MemExuOutput)))
765  val writebackHyuSta = Vec(params.HyuCnt, Flipped(DecoupledIO(new MemExuOutput)))
766  val writebackVldu = Vec(params.VlduCnt, Flipped(DecoupledIO(new MemExuOutput(true))))
767
768  val s3_delayed_load_error = Input(Vec(LoadPipelineWidth, Bool()))
769  val stIn = Input(Vec(params.StaExuCnt, ValidIO(new DynInst())))
770  val memoryViolation = Flipped(ValidIO(new Redirect))
771  val exceptionAddr = Input(new Bundle {
772    val vaddr = UInt(VAddrBits.W)
773    val gpaddr = UInt(GPAddrBits.W)
774  })
775  val sqDeq = Input(UInt(log2Ceil(EnsbufferWidth + 1).W))
776  val lqDeq = Input(UInt(log2Up(CommitWidth + 1).W))
777  val sqDeqPtr = Input(new SqPtr)
778  val lqDeqPtr = Input(new LqPtr)
779
780  val lqCancelCnt = Input(UInt(log2Up(VirtualLoadQueueSize + 1).W))
781  val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W))
782
783  val lqCanAccept = Input(Bool())
784  val sqCanAccept = Input(Bool())
785
786  val otherFastWakeup = Flipped(Vec(params.LduCnt + params.HyuCnt, ValidIO(new DynInst)))
787  val stIssuePtr = Input(new SqPtr())
788
789  val debugLS = Flipped(Output(new DebugLSIO))
790
791  val lsTopdownInfo = Vec(params.LduCnt + params.HyuCnt, Flipped(Output(new LsTopdownInfo)))
792  // Output
793  val redirect = ValidIO(new Redirect)   // rob flush MemBlock
794  val issueLda = MixedVec(Seq.fill(params.LduCnt)(DecoupledIO(new MemExuInput())))
795  val issueSta = MixedVec(Seq.fill(params.StaCnt)(DecoupledIO(new MemExuInput())))
796  val issueStd = MixedVec(Seq.fill(params.StdCnt)(DecoupledIO(new MemExuInput())))
797  val issueHylda = MixedVec(Seq.fill(params.HyuCnt)(DecoupledIO(new MemExuInput())))
798  val issueHysta = MixedVec(Seq.fill(params.HyuCnt)(DecoupledIO(new MemExuInput())))
799  val issueVldu = MixedVec(Seq.fill(params.VlduCnt)(DecoupledIO(new MemExuInput(true))))
800
801  val loadFastMatch = Vec(params.LduCnt, Output(UInt(params.LduCnt.W)))
802  val loadFastImm   = Vec(params.LduCnt, Output(UInt(12.W))) // Imm_I
803
804  val tlbCsr = Output(new TlbCsrBundle)
805  val csrCtrl = Output(new CustomCSRCtrlIO)
806  val sfence = Output(new SfenceBundle)
807  val isStoreException = Output(Bool())
808  val isVlsException = Output(Bool())
809
810  // ATTENTION: The issue ports' sequence order should be the same as IQs' deq config
811  private [backend] def issueUops: Seq[DecoupledIO[MemExuInput]] = {
812    issueSta ++
813      issueHylda ++ issueHysta ++
814      issueLda ++
815      issueVldu ++
816      issueStd
817  }.toSeq
818
819  // ATTENTION: The writeback ports' sequence order should be the same as IQs' deq config
820  private [backend] def writeBack: Seq[DecoupledIO[MemExuOutput]] = {
821    writebackSta ++
822      writebackHyuLda ++ writebackHyuSta ++
823      writebackLda ++
824      writebackVldu ++
825      writebackStd
826  }
827}
828
829class TopToBackendBundle(implicit p: Parameters) extends XSBundle {
830  val hartId            = Output(UInt(hartIdLen.W))
831  val externalInterrupt = Output(new ExternalInterruptIO)
832  val msiInfo           = Output(ValidIO(new MsiInfoBundle))
833  val clintTime         = Output(ValidIO(UInt(64.W)))
834}
835
836class BackendToTopBundle extends Bundle {
837  val cpuHalted = Output(Bool())
838}
839
840class BackendIO(implicit p: Parameters, params: BackendParams) extends XSBundle with HasSoCParameter {
841  val fromTop = Flipped(new TopToBackendBundle)
842
843  val toTop = new BackendToTopBundle
844
845  val fenceio = new FenceIO
846  // Todo: merge these bundles into BackendFrontendIO
847  val frontend = Flipped(new FrontendToCtrlIO)
848  val frontendSfence = Output(new SfenceBundle)
849  val frontendCsrCtrl = Output(new CustomCSRCtrlIO)
850  val frontendTlbCsr = Output(new TlbCsrBundle)
851  val frontendReset = Output(Reset())
852
853  val mem = new BackendMemIO
854
855  val perf = Input(new PerfCounterIO)
856
857  val tlb = Output(new TlbCsrBundle)
858
859  val csrCustomCtrl = Output(new CustomCSRCtrlIO)
860
861  val debugTopDown = new Bundle {
862    val fromRob = new RobCoreTopDownIO
863    val fromCore = new CoreDispatchTopDownIO
864  }
865  val debugRolling = new RobDebugRollingIO
866}
867