xref: /XiangShan/src/main/scala/xiangshan/XSCore.scala (revision 7a2fc509e2d355879c4db3dc3f17a6ccacd3d09e)
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
18
19import chipsalliance.rocketchip.config
20import chipsalliance.rocketchip.config.Parameters
21import chisel3._
22import chisel3.util._
23import freechips.rocketchip.diplomacy.{BundleBridgeSource, LazyModule, LazyModuleImp}
24import freechips.rocketchip.interrupts.{IntSinkNode, IntSinkPortSimple}
25import freechips.rocketchip.tile.HasFPUParameters
26import freechips.rocketchip.tilelink.TLBuffer
27import system.HasSoCParameter
28import utils._
29import xiangshan.backend._
30import xiangshan.backend.exu.{ExuConfig, Wb2Ctrl, WbArbiterWrapper}
31import xiangshan.cache.mmu._
32import xiangshan.frontend._
33
34import scala.collection.mutable.ListBuffer
35
36abstract class XSModule(implicit val p: Parameters) extends MultiIOModule
37  with HasXSParameter
38  with HasFPUParameters {
39  def io: Record
40}
41
42//remove this trait after impl module logic
43trait NeedImpl {
44  this: RawModule =>
45  override protected def IO[T <: Data](iodef: T): T = {
46    println(s"[Warn]: (${this.name}) please reomve 'NeedImpl' after implement this module")
47    val io = chisel3.experimental.IO(iodef)
48    io <> DontCare
49    io
50  }
51}
52
53class WritebackSourceParams(
54  var exuConfigs: Seq[Seq[ExuConfig]] = Seq()
55 ) {
56  def length: Int = exuConfigs.length
57  def ++(that: WritebackSourceParams): WritebackSourceParams = {
58    new WritebackSourceParams(exuConfigs ++ that.exuConfigs)
59  }
60}
61
62trait HasWritebackSource {
63  val writebackSourceParams: Seq[WritebackSourceParams]
64  final def writebackSource(sourceMod: HasWritebackSourceImp): Seq[Seq[Valid[ExuOutput]]] = {
65    require(sourceMod.writebackSource.isDefined, "should not use Valid[ExuOutput]")
66    val source = sourceMod.writebackSource.get
67    require(source.length == writebackSourceParams.length, "length mismatch between sources")
68    for ((s, p) <- source.zip(writebackSourceParams)) {
69      require(s.length == p.length, "params do not match with the exuOutput")
70    }
71    source
72  }
73  final def writebackSource1(sourceMod: HasWritebackSourceImp): Seq[Seq[DecoupledIO[ExuOutput]]] = {
74    require(sourceMod.writebackSource1.isDefined, "should not use DecoupledIO[ExuOutput]")
75    val source = sourceMod.writebackSource1.get
76    require(source.length == writebackSourceParams.length, "length mismatch between sources")
77    for ((s, p) <- source.zip(writebackSourceParams)) {
78      require(s.length == p.length, "params do not match with the exuOutput")
79    }
80    source
81  }
82  val writebackSourceImp: HasWritebackSourceImp
83}
84
85trait HasWritebackSourceImp {
86  def writebackSource: Option[Seq[Seq[Valid[ExuOutput]]]] = None
87  def writebackSource1: Option[Seq[Seq[DecoupledIO[ExuOutput]]]] = None
88}
89
90trait HasWritebackSink {
91  // Caches all sources. The selected source will be the one with smallest length.
92  var writebackSinks = ListBuffer.empty[(Seq[HasWritebackSource], Seq[Int])]
93  def addWritebackSink(source: Seq[HasWritebackSource], index: Option[Seq[Int]] = None): HasWritebackSink = {
94    val realIndex = if (index.isDefined) index.get else Seq.fill(source.length)(0)
95    writebackSinks += ((source, realIndex))
96    this
97  }
98
99  def writebackSinksParams: Seq[WritebackSourceParams] = {
100    writebackSinks.map{ case (s, i) => s.zip(i).map(x => x._1.writebackSourceParams(x._2)).reduce(_ ++ _) }
101  }
102  final def writebackSinksMod(
103     thisMod: Option[HasWritebackSource] = None,
104     thisModImp: Option[HasWritebackSourceImp] = None
105   ): Seq[Seq[HasWritebackSourceImp]] = {
106    require(thisMod.isDefined == thisModImp.isDefined)
107    writebackSinks.map(_._1.map(source =>
108      if (thisMod.isDefined && source == thisMod.get) thisModImp.get else source.writebackSourceImp)
109    )
110  }
111  final def writebackSinksImp(
112    thisMod: Option[HasWritebackSource] = None,
113    thisModImp: Option[HasWritebackSourceImp] = None
114  ): Seq[Seq[ValidIO[ExuOutput]]] = {
115    val sourceMod = writebackSinksMod(thisMod, thisModImp)
116    writebackSinks.zip(sourceMod).map{ case ((s, i), m) =>
117      s.zip(i).zip(m).flatMap(x => x._1._1.writebackSource(x._2)(x._1._2))
118    }
119  }
120  def selWritebackSinks(func: WritebackSourceParams => Int): Int = {
121    writebackSinksParams.zipWithIndex.minBy(params => func(params._1))._2
122  }
123  def generateWritebackIO(
124    thisMod: Option[HasWritebackSource] = None,
125    thisModImp: Option[HasWritebackSourceImp] = None
126   ): Unit
127}
128
129abstract class XSBundle(implicit val p: Parameters) extends Bundle
130  with HasXSParameter
131
132abstract class XSCoreBase()(implicit p: config.Parameters) extends LazyModule
133  with HasXSParameter with HasExuWbHelper
134{
135  // interrupt sinks
136  val clint_int_sink = IntSinkNode(IntSinkPortSimple(1, 2))
137  val debug_int_sink = IntSinkNode(IntSinkPortSimple(1, 1))
138  val plic_int_sink = IntSinkNode(IntSinkPortSimple(2, 1))
139  // outer facing nodes
140  val frontend = LazyModule(new Frontend())
141  val ptw = LazyModule(new L2TLBWrapper())
142  val ptw_to_l2_buffer = LazyModule(new TLBuffer)
143  val csrOut = BundleBridgeSource(Some(() => new DistributedCSRIO()))
144
145  ptw_to_l2_buffer.node := ptw.node
146
147  val wbArbiter = LazyModule(new WbArbiterWrapper(exuConfigs, NRIntWritePorts, NRFpWritePorts))
148  val intWbPorts = wbArbiter.intWbPorts
149  val fpWbPorts = wbArbiter.fpWbPorts
150
151  // TODO: better RS organization
152  // generate rs according to number of function units
153  require(exuParameters.JmpCnt == 1)
154  require(exuParameters.MduCnt <= exuParameters.AluCnt && exuParameters.MduCnt > 0)
155  require(exuParameters.FmiscCnt <= exuParameters.FmacCnt && exuParameters.FmiscCnt > 0)
156  require(exuParameters.LduCnt == exuParameters.StuCnt) // TODO: remove this limitation
157
158  // one RS every 2 MDUs
159  val schedulePorts = Seq(
160    // exuCfg, numDeq, intFastWakeupTarget, fpFastWakeupTarget
161    Seq(
162      (AluExeUnitCfg, exuParameters.AluCnt, Seq(AluExeUnitCfg, MulDivExeUnitCfg, JumpCSRExeUnitCfg, LdExeUnitCfg, StaExeUnitCfg), Seq()),
163      (MulDivExeUnitCfg, exuParameters.MduCnt, Seq(AluExeUnitCfg, MulDivExeUnitCfg), Seq()),
164      (JumpCSRExeUnitCfg, 1, Seq(), Seq()),
165      (LdExeUnitCfg, exuParameters.LduCnt, Seq(AluExeUnitCfg, LdExeUnitCfg), Seq()),
166      (StaExeUnitCfg, exuParameters.StuCnt, Seq(), Seq()),
167      (StdExeUnitCfg, exuParameters.StuCnt, Seq(), Seq())
168    ),
169    Seq(
170      (FmacExeUnitCfg, exuParameters.FmacCnt, Seq(), Seq(FmacExeUnitCfg, FmiscExeUnitCfg)),
171      (FmiscExeUnitCfg, exuParameters.FmiscCnt, Seq(), Seq())
172    )
173  )
174
175  // should do outer fast wakeup ports here
176  val otherFastPorts = schedulePorts.zipWithIndex.map { case (sche, i) =>
177    val otherCfg = schedulePorts.zipWithIndex.filter(_._2 != i).map(_._1).reduce(_ ++ _)
178    val outerPorts = sche.map(cfg => {
179      // exe units from this scheduler need fastUops from exeunits
180      val outerWakeupInSche = sche.filter(_._1.wakeupFromExu)
181      val intraIntScheOuter = outerWakeupInSche.filter(_._3.contains(cfg._1)).map(_._1)
182      val intraFpScheOuter = outerWakeupInSche.filter(_._4.contains(cfg._1)).map(_._1)
183      // exe units from other schedulers need fastUop from outside
184      val otherIntSource = otherCfg.filter(_._3.contains(cfg._1)).map(_._1)
185      val otherFpSource = otherCfg.filter(_._4.contains(cfg._1)).map(_._1)
186      val intSource = findInWbPorts(intWbPorts, intraIntScheOuter ++ otherIntSource)
187      val fpSource = findInWbPorts(fpWbPorts, intraFpScheOuter ++ otherFpSource)
188      getFastWakeupIndex(cfg._1, intSource, fpSource, intWbPorts.length).sorted
189    })
190    println(s"inter-scheduler wakeup sources for $i: $outerPorts")
191    outerPorts
192  }
193
194  // allow mdu and fmisc to have 2*numDeq enqueue ports
195  val intDpPorts = (0 until exuParameters.AluCnt).map(i => {
196    if (i < exuParameters.JmpCnt) Seq((0, i), (1, i), (2, i))
197    else if (i < 2 * exuParameters.MduCnt) Seq((0, i), (1, i))
198    else Seq((0, i))
199  })
200  val lsDpPorts = (0 until exuParameters.LduCnt).map(i => Seq((3, i))) ++
201                  (0 until exuParameters.StuCnt).map(i => Seq((4, i))) ++
202                  (0 until exuParameters.StuCnt).map(i => Seq((5, i)))
203  val fpDpPorts = (0 until exuParameters.FmacCnt).map(i => {
204    if (i < 2 * exuParameters.FmiscCnt) Seq((0, i), (1, i))
205    else Seq((0, i))
206  })
207
208  val dispatchPorts = Seq(intDpPorts ++ lsDpPorts, fpDpPorts)
209
210  val outIntRfReadPorts = Seq(0, 0)
211  val outFpRfReadPorts = Seq(0, StorePipelineWidth)
212  val hasIntRf = Seq(true, false)
213  val hasFpRf = Seq(false, true)
214  val exuBlocks = schedulePorts.zip(dispatchPorts).zip(otherFastPorts).zipWithIndex.map {
215    case (((sche, disp), other), i) =>
216      LazyModule(new ExuBlock(sche, disp, intWbPorts, fpWbPorts, other, outIntRfReadPorts(i), outFpRfReadPorts(i), hasIntRf(i), hasFpRf(i)))
217  }
218
219  val memBlock = LazyModule(new MemBlock()(p.alter((site, here, up) => {
220    case XSCoreParamsKey => up(XSCoreParamsKey).copy(
221      IssQueSize = exuBlocks.head.scheduler.getMemRsEntries
222    )
223  })))
224
225  val wb2Ctrl = LazyModule(new Wb2Ctrl(exuConfigs))
226  wb2Ctrl.addWritebackSink(exuBlocks :+ memBlock)
227  val ctrlBlock = LazyModule(new CtrlBlock)
228  val writebackSources = Seq(Seq(wb2Ctrl), Seq(wbArbiter))
229  writebackSources.foreach(s => ctrlBlock.addWritebackSink(s))
230}
231
232class XSCore()(implicit p: config.Parameters) extends XSCoreBase
233  with HasXSDts
234{
235  lazy val module = new XSCoreImp(this)
236}
237
238class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer)
239  with HasXSParameter
240  with HasSoCParameter {
241  val io = IO(new Bundle {
242    val hartId = Input(UInt(64.W))
243    val reset_vector = Input(UInt(PAddrBits.W))
244    val cpu_halt = Output(Bool())
245    val l2_pf_enable = Output(Bool())
246    val perfEvents = Input(Vec(numPCntHc * coreParams.L2NBanks, new PerfEvent))
247    val beu_errors = Output(new XSL1BusErrors())
248  })
249
250  println(s"FPGAPlatform:${env.FPGAPlatform} EnableDebug:${env.EnableDebug}")
251
252  val frontend = outer.frontend.module
253  val ctrlBlock = outer.ctrlBlock.module
254  val wb2Ctrl = outer.wb2Ctrl.module
255  val memBlock = outer.memBlock.module
256  val ptw = outer.ptw.module
257  val ptw_to_l2_buffer = outer.ptw_to_l2_buffer.module
258  val exuBlocks = outer.exuBlocks.map(_.module)
259
260  frontend.io.hartId  := io.hartId
261  ctrlBlock.io.hartId := io.hartId
262  exuBlocks.foreach(_.io.hartId := io.hartId)
263  memBlock.io.hartId := io.hartId
264  outer.wbArbiter.module.io.hartId := io.hartId
265  frontend.io.reset_vector := io.reset_vector
266
267  io.cpu_halt := ctrlBlock.io.cpu_halt
268
269  outer.wbArbiter.module.io.redirect <> ctrlBlock.io.redirect
270  val allWriteback = exuBlocks.flatMap(_.io.fuWriteback) ++ memBlock.io.writeback
271  require(exuConfigs.length == allWriteback.length, s"${exuConfigs.length} != ${allWriteback.length}")
272  outer.wbArbiter.module.io.in <> allWriteback
273  val rfWriteback = outer.wbArbiter.module.io.out
274
275  wb2Ctrl.io.redirect <> ctrlBlock.io.redirect
276  outer.wb2Ctrl.generateWritebackIO()
277
278  io.beu_errors.icache <> frontend.io.error.toL1BusErrorUnitInfo()
279  io.beu_errors.dcache <> memBlock.io.error.toL1BusErrorUnitInfo()
280
281  require(exuBlocks.count(_.fuConfigs.map(_._1).contains(JumpCSRExeUnitCfg)) == 1)
282  val csrFenceMod = exuBlocks.filter(_.fuConfigs.map(_._1).contains(JumpCSRExeUnitCfg)).head
283  val csrioIn = csrFenceMod.io.fuExtra.csrio.get
284  val fenceio = csrFenceMod.io.fuExtra.fenceio.get
285
286  frontend.io.backend <> ctrlBlock.io.frontend
287  frontend.io.sfence <> fenceio.sfence
288  frontend.io.tlbCsr <> csrioIn.tlb
289  frontend.io.csrCtrl <> csrioIn.customCtrl
290  frontend.io.fencei := fenceio.fencei
291
292  ctrlBlock.io.csrCtrl <> csrioIn.customCtrl
293  val redirectBlocks = exuBlocks.reverse.filter(_.fuConfigs.map(_._1).map(_.hasRedirect).reduce(_ || _))
294  ctrlBlock.io.exuRedirect <> redirectBlocks.flatMap(_.io.fuExtra.exuRedirect)
295  ctrlBlock.io.stIn <> memBlock.io.stIn
296  ctrlBlock.io.memoryViolation <> memBlock.io.memoryViolation
297  exuBlocks.head.io.scheExtra.enqLsq.get <> memBlock.io.enqLsq
298  exuBlocks.foreach(b => {
299    b.io.scheExtra.lcommit := ctrlBlock.io.robio.lsq.lcommit
300    b.io.scheExtra.scommit := memBlock.io.sqDeq
301    b.io.scheExtra.lqCancelCnt := memBlock.io.lqCancelCnt
302    b.io.scheExtra.sqCancelCnt := memBlock.io.sqCancelCnt
303  })
304  val sourceModules = outer.writebackSources.map(_.map(_.module.asInstanceOf[HasWritebackSourceImp]))
305  outer.ctrlBlock.generateWritebackIO()
306
307  val allFastUop = exuBlocks.flatMap(b => b.io.fastUopOut.dropRight(b.numOutFu)) ++ memBlock.io.otherFastWakeup
308  require(allFastUop.length == exuConfigs.length, s"${allFastUop.length} != ${exuConfigs.length}")
309  val intFastUop = allFastUop.zip(exuConfigs).filter(_._2.writeIntRf).map(_._1)
310  val fpFastUop = allFastUop.zip(exuConfigs).filter(_._2.writeFpRf).map(_._1)
311  val intFastUop1 = outer.wbArbiter.intConnections.map(c => intFastUop(c.head))
312  val fpFastUop1 = outer.wbArbiter.fpConnections.map(c => fpFastUop(c.head))
313  val allFastUop1 = intFastUop1 ++ fpFastUop1
314
315  ctrlBlock.io.dispatch <> exuBlocks.flatMap(_.io.in)
316
317  exuBlocks(0).io.scheExtra.fpRfReadIn.get <> exuBlocks(1).io.scheExtra.fpRfReadOut.get
318  exuBlocks(0).io.scheExtra.fpStateReadIn.get <> exuBlocks(1).io.scheExtra.fpStateReadOut.get
319
320  memBlock.io.issue <> exuBlocks(0).io.issue.get
321  // By default, instructions do not have exceptions when they enter the function units.
322  memBlock.io.issue.map(_.bits.uop.clearExceptions())
323  exuBlocks(0).io.scheExtra.loadFastMatch.get <> memBlock.io.loadFastMatch
324
325  val stdIssue = exuBlocks(0).io.issue.get.takeRight(exuParameters.StuCnt)
326  exuBlocks.map(_.io).foreach { exu =>
327    exu.redirect <> ctrlBlock.io.redirect
328    exu.allocPregs <> ctrlBlock.io.allocPregs
329    exu.rfWriteback <> rfWriteback
330    exu.fastUopIn <> allFastUop1
331    exu.scheExtra.jumpPc <> ctrlBlock.io.jumpPc
332    exu.scheExtra.jalr_target <> ctrlBlock.io.jalr_target
333    exu.scheExtra.stIssuePtr <> memBlock.io.stIssuePtr
334    exu.scheExtra.debug_fp_rat <> ctrlBlock.io.debug_fp_rat
335    exu.scheExtra.debug_int_rat <> ctrlBlock.io.debug_int_rat
336    exu.scheExtra.memWaitUpdateReq.staIssue.zip(memBlock.io.stIn).foreach{case (sink, src) => {
337      sink.bits := src.bits
338      sink.valid := src.valid
339    }}
340    exu.scheExtra.memWaitUpdateReq.stdIssue.zip(stdIssue).foreach{case (sink, src) => {
341      sink.valid := src.valid
342      sink.bits := src.bits
343    }}
344  }
345  XSPerfHistogram("fastIn_count", PopCount(allFastUop1.map(_.valid)), true.B, 0, allFastUop1.length, 1)
346  XSPerfHistogram("wakeup_count", PopCount(rfWriteback.map(_.valid)), true.B, 0, rfWriteback.length, 1)
347
348  ctrlBlock.perfinfo.perfEventsEu0 := exuBlocks(0).getPerf.dropRight(outer.exuBlocks(0).scheduler.numRs)
349  ctrlBlock.perfinfo.perfEventsEu1 := exuBlocks(1).getPerf.dropRight(outer.exuBlocks(1).scheduler.numRs)
350  memBlock.io.perfEventsPTW  := ptw.getPerf
351  ctrlBlock.perfinfo.perfEventsRs  := outer.exuBlocks.flatMap(b => b.module.getPerf.takeRight(b.scheduler.numRs))
352
353  csrioIn.hartId <> io.hartId
354  csrioIn.perf <> DontCare
355  csrioIn.perf.retiredInstr <> ctrlBlock.io.robio.toCSR.perfinfo.retiredInstr
356  csrioIn.perf.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo
357  csrioIn.perf.memInfo <> memBlock.io.memInfo
358  csrioIn.perf.frontendInfo <> frontend.io.frontendInfo
359
360  csrioIn.perf.perfEventsFrontend <> frontend.getPerf
361  csrioIn.perf.perfEventsCtrl     <> ctrlBlock.getPerf
362  csrioIn.perf.perfEventsLsu      <> memBlock.getPerf
363  csrioIn.perf.perfEventsHc       <> io.perfEvents
364
365  csrioIn.fpu.fflags <> ctrlBlock.io.robio.toCSR.fflags
366  csrioIn.fpu.isIllegal := false.B
367  csrioIn.fpu.dirty_fs <> ctrlBlock.io.robio.toCSR.dirty_fs
368  csrioIn.fpu.frm <> exuBlocks(1).io.fuExtra.frm.get
369  csrioIn.exception <> ctrlBlock.io.robio.exception
370  csrioIn.isXRet <> ctrlBlock.io.robio.toCSR.isXRet
371  csrioIn.trapTarget <> ctrlBlock.io.robio.toCSR.trapTarget
372  csrioIn.interrupt <> ctrlBlock.io.robio.toCSR.intrBitSet
373  csrioIn.wfi_event <> ctrlBlock.io.robio.toCSR.wfiEvent
374  csrioIn.memExceptionVAddr <> memBlock.io.lsqio.exceptionAddr.vaddr
375
376  csrioIn.externalInterrupt.msip := outer.clint_int_sink.in.head._1(0)
377  csrioIn.externalInterrupt.mtip := outer.clint_int_sink.in.head._1(1)
378  csrioIn.externalInterrupt.meip := outer.plic_int_sink.in.head._1(0)
379  csrioIn.externalInterrupt.seip := outer.plic_int_sink.in.last._1(0)
380  csrioIn.externalInterrupt.debug := outer.debug_int_sink.in.head._1(0)
381
382  csrioIn.distributedUpdate(0).w.valid := memBlock.io.csrUpdate.w.valid
383  csrioIn.distributedUpdate(0).w.bits := memBlock.io.csrUpdate.w.bits
384  csrioIn.distributedUpdate(1).w.valid := frontend.io.csrUpdate.w.valid
385  csrioIn.distributedUpdate(1).w.bits := frontend.io.csrUpdate.w.bits
386
387  fenceio.sfence <> memBlock.io.sfence
388  fenceio.sbuffer <> memBlock.io.fenceToSbuffer
389
390  memBlock.io.redirect <> ctrlBlock.io.redirect
391  memBlock.io.rsfeedback <> exuBlocks(0).io.scheExtra.feedback.get
392  memBlock.io.csrCtrl <> csrioIn.customCtrl
393  memBlock.io.tlbCsr <> csrioIn.tlb
394  memBlock.io.lsqio.rob <> ctrlBlock.io.robio.lsq
395  memBlock.io.lsqio.exceptionAddr.isStore := CommitType.lsInstIsStore(ctrlBlock.io.robio.exception.bits.uop.ctrl.commitType)
396
397  val itlbRepeater1 = PTWRepeater(frontend.io.ptw, fenceio.sfence, csrioIn.tlb)
398  val itlbRepeater2 = PTWRepeater(itlbRepeater1.io.ptw, ptw.io.tlb(0), fenceio.sfence, csrioIn.tlb)
399  val dtlbRepeater1  = PTWFilter(memBlock.io.ptw, fenceio.sfence, csrioIn.tlb, l2tlbParams.filterSize)
400  val dtlbRepeater2  = PTWRepeaterNB(passReady = false, dtlbRepeater1.io.ptw, ptw.io.tlb(1), fenceio.sfence, csrioIn.tlb)
401  ptw.io.sfence <> fenceio.sfence
402  ptw.io.csr.tlb <> csrioIn.tlb
403  ptw.io.csr.distribute_csr <> csrioIn.customCtrl.distribute_csr
404
405  // if l2 prefetcher use stream prefetch, it should be placed in XSCore
406  io.l2_pf_enable := csrioIn.customCtrl.l2_pf_enable
407
408  // Modules are reset one by one
409  val resetTree = ResetGenNode(
410    Seq(
411      ModuleNode(memBlock), ModuleNode(dtlbRepeater1),
412      ResetGenNode(Seq(
413        ModuleNode(itlbRepeater2),
414        ModuleNode(ptw),
415        ModuleNode(dtlbRepeater2),
416        ModuleNode(ptw_to_l2_buffer),
417      )),
418      ResetGenNode(Seq(
419        ModuleNode(exuBlocks.head),
420        ResetGenNode(
421          exuBlocks.tail.map(m => ModuleNode(m)) :+ ModuleNode(outer.wbArbiter.module)
422        ),
423        ResetGenNode(Seq(
424          ModuleNode(ctrlBlock),
425          ResetGenNode(Seq(
426            ModuleNode(frontend), ModuleNode(itlbRepeater1)
427          ))
428        ))
429      ))
430    )
431  )
432
433  ResetGen(resetTree, reset.asBool, !debugOpts.FPGAPlatform)
434
435}
436