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