xref: /XiangShan/src/main/scala/xiangshan/XSCore.scala (revision 57bb43b5f11c3f1e89ac52f232fe73056b35d9bd)
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 PTWWrapper())
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 == 2 && exuParameters.StuCnt == 2)
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 = Seq(
201    Seq((3, 0)),
202    Seq((3, 1)),
203    Seq((4, 0)),
204    Seq((4, 1))
205  ) ++ (0 until exuParameters.StuCnt).map(i => Seq((5, i)))
206  val fpDpPorts = (0 until exuParameters.FmacCnt).map(i => {
207    if (i < 2 * exuParameters.FmiscCnt) Seq((0, i), (1, i))
208    else Seq((0, i))
209  })
210
211  val dispatchPorts = Seq(intDpPorts ++ lsDpPorts, fpDpPorts)
212
213  val outIntRfReadPorts = Seq(0, 0)
214  val outFpRfReadPorts = Seq(0, 2)
215  val hasIntRf = Seq(true, false)
216  val hasFpRf = Seq(false, true)
217  val exuBlocks = schedulePorts.zip(dispatchPorts).zip(otherFastPorts).zipWithIndex.map {
218    case (((sche, disp), other), i) =>
219      LazyModule(new ExuBlock(sche, disp, intWbPorts, fpWbPorts, other, outIntRfReadPorts(i), outFpRfReadPorts(i), hasIntRf(i), hasFpRf(i)))
220  }
221
222  val memBlock = LazyModule(new MemBlock()(p.alter((site, here, up) => {
223    case XSCoreParamsKey => up(XSCoreParamsKey).copy(
224      IssQueSize = exuBlocks.head.scheduler.memRsEntries.max
225    )
226  })))
227
228  val wb2Ctrl = LazyModule(new Wb2Ctrl(exuConfigs))
229  wb2Ctrl.addWritebackSink(exuBlocks :+ memBlock)
230  val ctrlBlock = LazyModule(new CtrlBlock)
231  val writebackSources = Seq(Seq(wb2Ctrl), Seq(wbArbiter))
232  writebackSources.foreach(s => ctrlBlock.addWritebackSink(s))
233}
234
235class XSCore()(implicit p: config.Parameters) extends XSCoreBase
236  with HasXSDts
237{
238  lazy val module = new XSCoreImp(this)
239}
240
241class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer)
242  with HasXSParameter
243  with HasSoCParameter {
244  val io = IO(new Bundle {
245    val hartId = Input(UInt(64.W))
246    val l2_pf_enable = Output(Bool())
247    val perfEvents = Input(Vec(numPCntHc * coreParams.L2NBanks, new PerfEvent))
248    val beu_errors = Output(new XSL1BusErrors())
249  })
250
251  println(s"FPGAPlatform:${env.FPGAPlatform} EnableDebug:${env.EnableDebug}")
252
253  val frontend = outer.frontend.module
254  val ctrlBlock = outer.ctrlBlock.module
255  val wb2Ctrl = outer.wb2Ctrl.module
256  val memBlock = outer.memBlock.module
257  val ptw = outer.ptw.module
258  val ptw_to_l2_buffer = outer.ptw_to_l2_buffer.module
259  val exuBlocks = outer.exuBlocks.map(_.module)
260
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
266  outer.wbArbiter.module.io.redirect <> ctrlBlock.io.redirect
267  val allWriteback = exuBlocks.flatMap(_.io.fuWriteback) ++ memBlock.io.writeback
268  require(exuConfigs.length == allWriteback.length, s"${exuConfigs.length} != ${allWriteback.length}")
269  outer.wbArbiter.module.io.in <> allWriteback
270  val rfWriteback = outer.wbArbiter.module.io.out
271
272  wb2Ctrl.io.redirect <> ctrlBlock.io.redirect
273  outer.wb2Ctrl.generateWritebackIO()
274
275  io.beu_errors.icache <> frontend.io.error.toL1BusErrorUnitInfo()
276  io.beu_errors.dcache <> memBlock.io.error.toL1BusErrorUnitInfo()
277
278  require(exuBlocks.count(_.fuConfigs.map(_._1).contains(JumpCSRExeUnitCfg)) == 1)
279  val csrFenceMod = exuBlocks.filter(_.fuConfigs.map(_._1).contains(JumpCSRExeUnitCfg)).head
280  val csrioIn = csrFenceMod.io.fuExtra.csrio.get
281  val fenceio = csrFenceMod.io.fuExtra.fenceio.get
282
283  frontend.io.backend <> ctrlBlock.io.frontend
284  frontend.io.sfence <> fenceio.sfence
285  frontend.io.tlbCsr <> csrioIn.tlb
286  frontend.io.csrCtrl <> csrioIn.customCtrl
287  frontend.io.fencei := fenceio.fencei
288
289  ctrlBlock.io.csrCtrl <> csrioIn.customCtrl
290  val redirectBlocks = exuBlocks.reverse.filter(_.fuConfigs.map(_._1).map(_.hasRedirect).reduce(_ || _))
291  ctrlBlock.io.exuRedirect <> redirectBlocks.flatMap(_.io.fuExtra.exuRedirect)
292  ctrlBlock.io.stIn <> memBlock.io.stIn
293  ctrlBlock.io.memoryViolation <> memBlock.io.memoryViolation
294  exuBlocks.head.io.scheExtra.enqLsq.get <> memBlock.io.enqLsq
295  exuBlocks.foreach(b => {
296    b.io.scheExtra.lcommit := ctrlBlock.io.robio.lsq.lcommit
297    b.io.scheExtra.scommit := memBlock.io.sqDeq
298    b.io.scheExtra.lqCancelCnt := memBlock.io.lqCancelCnt
299    b.io.scheExtra.sqCancelCnt := memBlock.io.sqCancelCnt
300  })
301  val sourceModules = outer.writebackSources.map(_.map(_.module.asInstanceOf[HasWritebackSourceImp]))
302  outer.ctrlBlock.generateWritebackIO()
303
304  val allFastUop = exuBlocks.flatMap(b => b.io.fastUopOut.dropRight(b.numOutFu)) ++ memBlock.io.otherFastWakeup
305  require(allFastUop.length == exuConfigs.length, s"${allFastUop.length} != ${exuConfigs.length}")
306  val intFastUop = allFastUop.zip(exuConfigs).filter(_._2.writeIntRf).map(_._1)
307  val fpFastUop = allFastUop.zip(exuConfigs).filter(_._2.writeFpRf).map(_._1)
308  val intFastUop1 = outer.wbArbiter.intConnections.map(c => intFastUop(c.head))
309  val fpFastUop1 = outer.wbArbiter.fpConnections.map(c => fpFastUop(c.head))
310  val allFastUop1 = intFastUop1 ++ fpFastUop1
311
312  ctrlBlock.io.dispatch <> exuBlocks.flatMap(_.io.in)
313
314  exuBlocks(0).io.scheExtra.fpRfReadIn.get <> exuBlocks(1).io.scheExtra.fpRfReadOut.get
315  exuBlocks(0).io.scheExtra.fpStateReadIn.get <> exuBlocks(1).io.scheExtra.fpStateReadOut.get
316
317  memBlock.io.issue <> exuBlocks(0).io.issue.get
318  // By default, instructions do not have exceptions when they enter the function units.
319  memBlock.io.issue.map(_.bits.uop.clearExceptions())
320  exuBlocks(0).io.scheExtra.loadFastMatch.get <> memBlock.io.loadFastMatch
321
322  val stdIssue = exuBlocks(0).io.issue.get.takeRight(exuParameters.StuCnt)
323  exuBlocks.map(_.io).foreach { exu =>
324    exu.redirect <> ctrlBlock.io.redirect
325    exu.allocPregs <> ctrlBlock.io.allocPregs
326    exu.rfWriteback <> rfWriteback
327    exu.fastUopIn <> allFastUop1
328    exu.scheExtra.jumpPc <> ctrlBlock.io.jumpPc
329    exu.scheExtra.jalr_target <> ctrlBlock.io.jalr_target
330    exu.scheExtra.stIssuePtr <> memBlock.io.stIssuePtr
331    exu.scheExtra.debug_fp_rat <> ctrlBlock.io.debug_fp_rat
332    exu.scheExtra.debug_int_rat <> ctrlBlock.io.debug_int_rat
333    exu.scheExtra.memWaitUpdateReq.staIssue.zip(memBlock.io.stIn).foreach{case (sink, src) => {
334      sink.bits := src.bits
335      sink.valid := src.valid
336    }}
337    exu.scheExtra.memWaitUpdateReq.stdIssue.zip(stdIssue).foreach{case (sink, src) => {
338      sink.valid := src.valid
339      sink.bits := src.bits
340    }}
341  }
342  XSPerfHistogram("fastIn_count", PopCount(allFastUop1.map(_.valid)), true.B, 0, allFastUop1.length, 1)
343  XSPerfHistogram("wakeup_count", PopCount(rfWriteback.map(_.valid)), true.B, 0, rfWriteback.length, 1)
344
345  ctrlBlock.perfinfo.perfEventsEu0 := exuBlocks(0).getPerf.dropRight(outer.exuBlocks(0).scheduler.numRs)
346  ctrlBlock.perfinfo.perfEventsEu1 := exuBlocks(1).getPerf.dropRight(outer.exuBlocks(1).scheduler.numRs)
347  memBlock.io.perfEventsPTW  := ptw.getPerf
348  ctrlBlock.perfinfo.perfEventsRs  := outer.exuBlocks.flatMap(b => b.module.getPerf.takeRight(b.scheduler.numRs))
349
350  csrioIn.hartId <> io.hartId
351  csrioIn.perf <> DontCare
352  csrioIn.perf.retiredInstr <> ctrlBlock.io.robio.toCSR.perfinfo.retiredInstr
353  csrioIn.perf.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo
354  csrioIn.perf.memInfo <> memBlock.io.memInfo
355  csrioIn.perf.frontendInfo <> frontend.io.frontendInfo
356
357  csrioIn.perf.perfEventsFrontend <> frontend.getPerf
358  csrioIn.perf.perfEventsCtrl     <> ctrlBlock.getPerf
359  csrioIn.perf.perfEventsLsu      <> memBlock.getPerf
360  csrioIn.perf.perfEventsHc       <> io.perfEvents
361
362  csrioIn.fpu.fflags <> ctrlBlock.io.robio.toCSR.fflags
363  csrioIn.fpu.isIllegal := false.B
364  csrioIn.fpu.dirty_fs <> ctrlBlock.io.robio.toCSR.dirty_fs
365  csrioIn.fpu.frm <> exuBlocks(1).io.fuExtra.frm.get
366  csrioIn.exception <> ctrlBlock.io.robio.exception
367  csrioIn.isXRet <> ctrlBlock.io.robio.toCSR.isXRet
368  csrioIn.trapTarget <> ctrlBlock.io.robio.toCSR.trapTarget
369  csrioIn.interrupt <> ctrlBlock.io.robio.toCSR.intrBitSet
370  csrioIn.memExceptionVAddr <> memBlock.io.lsqio.exceptionAddr.vaddr
371
372  csrioIn.externalInterrupt.msip := outer.clint_int_sink.in.head._1(0)
373  csrioIn.externalInterrupt.mtip := outer.clint_int_sink.in.head._1(1)
374  csrioIn.externalInterrupt.meip := outer.plic_int_sink.in.head._1(0)
375  csrioIn.externalInterrupt.seip := outer.plic_int_sink.in.last._1(0)
376  csrioIn.externalInterrupt.debug := outer.debug_int_sink.in.head._1(0)
377
378  csrioIn.distributedUpdate(0).w.valid := memBlock.io.csrUpdate.w.valid
379  csrioIn.distributedUpdate(0).w.bits := memBlock.io.csrUpdate.w.bits
380  csrioIn.distributedUpdate(1).w.valid := frontend.io.csrUpdate.w.valid
381  csrioIn.distributedUpdate(1).w.bits := frontend.io.csrUpdate.w.bits
382
383  fenceio.sfence <> memBlock.io.sfence
384  fenceio.sbuffer <> memBlock.io.fenceToSbuffer
385
386  memBlock.io.redirect <> ctrlBlock.io.redirect
387  memBlock.io.rsfeedback <> exuBlocks(0).io.scheExtra.feedback.get
388  memBlock.io.csrCtrl <> csrioIn.customCtrl
389  memBlock.io.tlbCsr <> csrioIn.tlb
390  memBlock.io.lsqio.rob <> ctrlBlock.io.robio.lsq
391  memBlock.io.lsqio.exceptionAddr.isStore := CommitType.lsInstIsStore(ctrlBlock.io.robio.exception.bits.uop.ctrl.commitType)
392
393  val itlbRepeater1 = PTWRepeater(frontend.io.ptw, fenceio.sfence, csrioIn.tlb)
394  val itlbRepeater2 = PTWRepeater(itlbRepeater1.io.ptw, ptw.io.tlb(0), fenceio.sfence, csrioIn.tlb)
395  val dtlbRepeater1  = PTWFilter(memBlock.io.ptw, fenceio.sfence, csrioIn.tlb, l2tlbParams.filterSize)
396  val dtlbRepeater2  = PTWRepeaterNB(passReady = false, dtlbRepeater1.io.ptw, ptw.io.tlb(1), fenceio.sfence, csrioIn.tlb)
397  ptw.io.sfence <> fenceio.sfence
398  ptw.io.csr.tlb <> csrioIn.tlb
399  ptw.io.csr.distribute_csr <> csrioIn.customCtrl.distribute_csr
400
401  // if l2 prefetcher use stream prefetch, it should be placed in XSCore
402  io.l2_pf_enable := csrioIn.customCtrl.l2_pf_enable
403
404  // Modules are reset one by one
405  val resetTree = ResetGenNode(
406    Seq(
407      ModuleNode(memBlock), ModuleNode(dtlbRepeater1),
408      ResetGenNode(Seq(
409        ModuleNode(itlbRepeater2),
410        ModuleNode(ptw),
411        ModuleNode(dtlbRepeater2),
412        ModuleNode(ptw_to_l2_buffer),
413      )),
414      ResetGenNode(Seq(
415        ModuleNode(exuBlocks.head),
416        ResetGenNode(
417          exuBlocks.tail.map(m => ModuleNode(m)) :+ ModuleNode(outer.wbArbiter.module)
418        ),
419        ResetGenNode(Seq(
420          ModuleNode(ctrlBlock),
421          ResetGenNode(Seq(
422            ModuleNode(frontend), ModuleNode(itlbRepeater1)
423          ))
424        ))
425      ))
426    )
427  )
428
429  ResetGen(resetTree, reset.asBool, !debugOpts.FPGAPlatform)
430
431}
432