xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision 887862dbb8debde8ab099befc426493834a69ee7)
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
239  intScheduler.io.fromTop.hartId := io.fromTop.hartId
240  intScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush
241  intScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs
242  intScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.intUops
243  intScheduler.io.intWriteBack := wbDataPath.io.toIntPreg
244  intScheduler.io.fpWriteBack := 0.U.asTypeOf(intScheduler.io.fpWriteBack)
245  intScheduler.io.vfWriteBack := 0.U.asTypeOf(intScheduler.io.vfWriteBack)
246  intScheduler.io.v0WriteBack := 0.U.asTypeOf(intScheduler.io.v0WriteBack)
247  intScheduler.io.vlWriteBack := 0.U.asTypeOf(intScheduler.io.vlWriteBack)
248  intScheduler.io.fromDataPath.resp := dataPath.io.toIntIQ
249  intScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) }
250  intScheduler.io.fromDataPath.og0Cancel := og0Cancel
251  intScheduler.io.fromDataPath.og1Cancel := og1Cancel
252  intScheduler.io.ldCancel := io.mem.ldCancel
253  intScheduler.io.fromDataPath.replaceRCIdx.get := dataPath.io.toWakeupQueueRCIdx.take(params.getIntExuRCWriteSize)
254  intScheduler.io.vlWriteBackInfo.vlIsZero := false.B
255  intScheduler.io.vlWriteBackInfo.vlIsVlmax := false.B
256
257  fpScheduler.io.fromTop.hartId := io.fromTop.hartId
258  fpScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush
259  fpScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs
260  fpScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.fpUops
261  fpScheduler.io.intWriteBack := 0.U.asTypeOf(fpScheduler.io.intWriteBack)
262  fpScheduler.io.fpWriteBack := wbDataPath.io.toFpPreg
263  fpScheduler.io.vfWriteBack := 0.U.asTypeOf(fpScheduler.io.vfWriteBack)
264  fpScheduler.io.v0WriteBack := 0.U.asTypeOf(fpScheduler.io.v0WriteBack)
265  fpScheduler.io.vlWriteBack := 0.U.asTypeOf(fpScheduler.io.vlWriteBack)
266  fpScheduler.io.fromDataPath.resp := dataPath.io.toFpIQ
267  fpScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) }
268  fpScheduler.io.fromDataPath.og0Cancel := og0Cancel
269  fpScheduler.io.fromDataPath.og1Cancel := og1Cancel
270  fpScheduler.io.ldCancel := io.mem.ldCancel
271  fpScheduler.io.vlWriteBackInfo.vlIsZero := false.B
272  fpScheduler.io.vlWriteBackInfo.vlIsVlmax := false.B
273
274  memScheduler.io.fromTop.hartId := io.fromTop.hartId
275  memScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush
276  memScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs
277  memScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.memUops
278  memScheduler.io.intWriteBack := wbDataPath.io.toIntPreg
279  memScheduler.io.fpWriteBack := wbDataPath.io.toFpPreg
280  memScheduler.io.vfWriteBack := wbDataPath.io.toVfPreg
281  memScheduler.io.v0WriteBack := wbDataPath.io.toV0Preg
282  memScheduler.io.vlWriteBack := wbDataPath.io.toVlPreg
283  memScheduler.io.fromMem.get.scommit := io.mem.sqDeq
284  memScheduler.io.fromMem.get.lcommit := io.mem.lqDeq
285  memScheduler.io.fromMem.get.wakeup := io.mem.wakeup
286  memScheduler.io.fromMem.get.sqDeqPtr := io.mem.sqDeqPtr
287  memScheduler.io.fromMem.get.lqDeqPtr := io.mem.lqDeqPtr
288  memScheduler.io.fromMem.get.sqCancelCnt := io.mem.sqCancelCnt
289  memScheduler.io.fromMem.get.lqCancelCnt := io.mem.lqCancelCnt
290  memScheduler.io.fromMem.get.stIssuePtr := io.mem.stIssuePtr
291  require(memScheduler.io.fromMem.get.memWaitUpdateReq.robIdx.length == io.mem.stIn.length)
292  memScheduler.io.fromMem.get.memWaitUpdateReq.robIdx.zip(io.mem.stIn).foreach { case (sink, source) =>
293    sink.valid := source.valid
294    sink.bits  := source.bits.robIdx
295  }
296  memScheduler.io.fromMem.get.memWaitUpdateReq.sqIdx := DontCare // TODO
297  memScheduler.io.fromDataPath.resp := dataPath.io.toMemIQ
298  memScheduler.io.fromMem.get.ldaFeedback := io.mem.ldaIqFeedback
299  memScheduler.io.fromMem.get.staFeedback := io.mem.staIqFeedback
300  memScheduler.io.fromMem.get.hyuFeedback := io.mem.hyuIqFeedback
301  memScheduler.io.fromMem.get.vstuFeedback := io.mem.vstuIqFeedback
302  memScheduler.io.fromMem.get.vlduFeedback := io.mem.vlduIqFeedback
303  memScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) }
304  memScheduler.io.fromDataPath.og0Cancel := og0Cancel
305  memScheduler.io.fromDataPath.og1Cancel := og1Cancel
306  memScheduler.io.ldCancel := io.mem.ldCancel
307  memScheduler.io.fromDataPath.replaceRCIdx.get := dataPath.io.toWakeupQueueRCIdx.takeRight(params.getMemExuRCWriteSize)
308  memScheduler.io.vlWriteBackInfo.vlIsZero := vlIsZero
309  memScheduler.io.vlWriteBackInfo.vlIsVlmax := vlIsVlmax
310
311  vfScheduler.io.fromTop.hartId := io.fromTop.hartId
312  vfScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush
313  vfScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs
314  vfScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.vfUops
315  vfScheduler.io.intWriteBack := 0.U.asTypeOf(vfScheduler.io.intWriteBack)
316  vfScheduler.io.fpWriteBack := 0.U.asTypeOf(vfScheduler.io.fpWriteBack)
317  vfScheduler.io.vfWriteBack := wbDataPath.io.toVfPreg
318  vfScheduler.io.v0WriteBack := wbDataPath.io.toV0Preg
319  vfScheduler.io.vlWriteBack := wbDataPath.io.toVlPreg
320  vfScheduler.io.fromDataPath.resp := dataPath.io.toVfIQ
321  vfScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) }
322  vfScheduler.io.fromDataPath.og0Cancel := og0Cancel
323  vfScheduler.io.fromDataPath.og1Cancel := og1Cancel
324  vfScheduler.io.ldCancel := io.mem.ldCancel
325  vfScheduler.io.vlWriteBackInfo.vlIsZero := vlIsZero
326  vfScheduler.io.vlWriteBackInfo.vlIsVlmax := vlIsVlmax
327  vfScheduler.io.fromOg2.get := og2ForVector.io.toVfIQ
328
329  dataPath.io.hartId := io.fromTop.hartId
330  dataPath.io.flush := ctrlBlock.io.toDataPath.flush
331
332  dataPath.io.fromIntIQ <> intScheduler.io.toDataPathAfterDelay
333  dataPath.io.fromFpIQ <> fpScheduler.io.toDataPathAfterDelay
334  dataPath.io.fromVfIQ <> vfScheduler.io.toDataPathAfterDelay
335  dataPath.io.fromMemIQ <> memScheduler.io.toDataPathAfterDelay
336
337  dataPath.io.ldCancel := io.mem.ldCancel
338
339  println(s"[Backend] wbDataPath.io.toIntPreg: ${wbDataPath.io.toIntPreg.size}, dataPath.io.fromIntWb: ${dataPath.io.fromIntWb.size}")
340  println(s"[Backend] wbDataPath.io.toVfPreg: ${wbDataPath.io.toVfPreg.size}, dataPath.io.fromFpWb: ${dataPath.io.fromVfWb.size}")
341  dataPath.io.fromIntWb := wbDataPath.io.toIntPreg
342  dataPath.io.fromFpWb := wbDataPath.io.toFpPreg
343  dataPath.io.fromVfWb := wbDataPath.io.toVfPreg
344  dataPath.io.fromV0Wb := wbDataPath.io.toV0Preg
345  dataPath.io.fromVlWb := wbDataPath.io.toVlPreg
346  dataPath.io.debugIntRat    .foreach(_ := ctrlBlock.io.debug_int_rat.get)
347  dataPath.io.debugFpRat     .foreach(_ := ctrlBlock.io.debug_fp_rat.get)
348  dataPath.io.debugVecRat    .foreach(_ := ctrlBlock.io.debug_vec_rat.get)
349  dataPath.io.debugV0Rat     .foreach(_ := ctrlBlock.io.debug_v0_rat.get)
350  dataPath.io.debugVlRat     .foreach(_ := ctrlBlock.io.debug_vl_rat.get)
351  dataPath.io.fromBypassNetwork := bypassNetwork.io.toDataPath
352
353  og2ForVector.io.flush := ctrlBlock.io.toDataPath.flush
354  og2ForVector.io.ldCancel := io.mem.ldCancel
355  og2ForVector.io.fromOg1NoReg <> dataPath.io.toVecExu
356  og2ForVector.io.fromOg1ImmInfo := dataPath.io.og1ImmInfo.zip(params.allExuParams).filter(_._2.isVfExeUnit).map(_._1)
357
358  bypassNetwork.io.fromDataPath.int <> dataPath.io.toIntExu
359  bypassNetwork.io.fromDataPath.fp <> dataPath.io.toFpExu
360  bypassNetwork.io.fromDataPath.vf <> og2ForVector.io.toVfExu
361  bypassNetwork.io.fromDataPath.mem <> dataPath.io.toMemExu
362  bypassNetwork.io.fromDataPath.immInfo := dataPath.io.og1ImmInfo
363  bypassNetwork.io.fromDataPath.immInfo.zip(params.allExuParams).filter(_._2.isVfExeUnit).map(_._1).zip(og2ForVector.io.toVfImmInfo).map{
364    case (vfImmInfo, og2ImmInfo) => vfImmInfo := og2ImmInfo
365  }
366  bypassNetwork.io.fromDataPath.rcData := dataPath.io.toBypassNetworkRCData
367  bypassNetwork.io.fromExus.connectExuOutput(_.int)(intExuBlock.io.out)
368  bypassNetwork.io.fromExus.connectExuOutput(_.fp)(fpExuBlock.io.out)
369  bypassNetwork.io.fromExus.connectExuOutput(_.vf)(vfExuBlock.io.out)
370
371  require(bypassNetwork.io.fromExus.mem.flatten.size == io.mem.writeBack.size,
372    s"bypassNetwork.io.fromExus.mem.flatten.size(${bypassNetwork.io.fromExus.mem.flatten.size}: ${bypassNetwork.io.fromExus.mem.map(_.size)}, " +
373    s"io.mem.writeback(${io.mem.writeBack.size})"
374  )
375  bypassNetwork.io.fromExus.mem.flatten.zip(io.mem.writeBack).foreach { case (sink, source) =>
376    sink.valid := source.valid
377    sink.bits.intWen := source.bits.uop.rfWen && FuType.isLoad(source.bits.uop.fuType)
378    sink.bits.pdest := source.bits.uop.pdest
379    sink.bits.data := source.bits.data
380  }
381
382
383  intExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush
384  for (i <- 0 until intExuBlock.io.in.length) {
385    for (j <- 0 until intExuBlock.io.in(i).length) {
386      val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.int(i)(j).bits.loadDependency, io.mem.ldCancel)
387      NewPipelineConnect(
388        bypassNetwork.io.toExus.int(i)(j), intExuBlock.io.in(i)(j), intExuBlock.io.in(i)(j).fire,
389        Mux(
390          bypassNetwork.io.toExus.int(i)(j).fire,
391          bypassNetwork.io.toExus.int(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel,
392          intExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush)
393        ),
394        Option("bypassNetwork2intExuBlock")
395      )
396    }
397  }
398
399  pcTargetMem.io.fromFrontendFtq := io.frontend.fromFtq
400  pcTargetMem.io.toDataPath <> dataPath.io.fromPcTargetMem
401
402  private val csrin = intExuBlock.io.csrin.get
403  csrin.hartId := io.fromTop.hartId
404  csrin.msiInfo.valid := RegNext(io.fromTop.msiInfo.valid)
405  csrin.msiInfo.bits := RegEnable(io.fromTop.msiInfo.bits, io.fromTop.msiInfo.valid)
406  csrin.clintTime.valid := RegNext(io.fromTop.clintTime.valid)
407  csrin.clintTime.bits := RegEnable(io.fromTop.clintTime.bits, io.fromTop.clintTime.valid)
408  csrin.trapInstInfo := ctrlBlock.io.toCSR.trapInstInfo
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