xref: /XiangShan/src/main/scala/xiangshan/XSCore.scala (revision b6900d94367091fbb4cb9feba8b6d31560bed207)
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 == 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 cpu_halt = Output(Bool())
247    val l2_pf_enable = Output(Bool())
248    val perfEvents = Input(Vec(numPCntHc * coreParams.L2NBanks, new PerfEvent))
249    val beu_errors = Output(new XSL1BusErrors())
250  })
251
252  println(s"FPGAPlatform:${env.FPGAPlatform} EnableDebug:${env.EnableDebug}")
253
254  val frontend = outer.frontend.module
255  val ctrlBlock = outer.ctrlBlock.module
256  val wb2Ctrl = outer.wb2Ctrl.module
257  val memBlock = outer.memBlock.module
258  val ptw = outer.ptw.module
259  val ptw_to_l2_buffer = outer.ptw_to_l2_buffer.module
260  val exuBlocks = outer.exuBlocks.map(_.module)
261
262  ctrlBlock.io.hartId := io.hartId
263  exuBlocks.foreach(_.io.hartId := io.hartId)
264  memBlock.io.hartId := io.hartId
265  outer.wbArbiter.module.io.hartId := io.hartId
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.memExceptionVAddr <> memBlock.io.lsqio.exceptionAddr.vaddr
374
375  csrioIn.externalInterrupt.msip := outer.clint_int_sink.in.head._1(0)
376  csrioIn.externalInterrupt.mtip := outer.clint_int_sink.in.head._1(1)
377  csrioIn.externalInterrupt.meip := outer.plic_int_sink.in.head._1(0)
378  csrioIn.externalInterrupt.seip := outer.plic_int_sink.in.last._1(0)
379  csrioIn.externalInterrupt.debug := outer.debug_int_sink.in.head._1(0)
380
381  csrioIn.distributedUpdate(0).w.valid := memBlock.io.csrUpdate.w.valid
382  csrioIn.distributedUpdate(0).w.bits := memBlock.io.csrUpdate.w.bits
383  csrioIn.distributedUpdate(1).w.valid := frontend.io.csrUpdate.w.valid
384  csrioIn.distributedUpdate(1).w.bits := frontend.io.csrUpdate.w.bits
385
386  fenceio.sfence <> memBlock.io.sfence
387  fenceio.sbuffer <> memBlock.io.fenceToSbuffer
388
389  memBlock.io.redirect <> ctrlBlock.io.redirect
390  memBlock.io.rsfeedback <> exuBlocks(0).io.scheExtra.feedback.get
391  memBlock.io.csrCtrl <> csrioIn.customCtrl
392  memBlock.io.tlbCsr <> csrioIn.tlb
393  memBlock.io.lsqio.rob <> ctrlBlock.io.robio.lsq
394  memBlock.io.lsqio.exceptionAddr.isStore := CommitType.lsInstIsStore(ctrlBlock.io.robio.exception.bits.uop.ctrl.commitType)
395
396  val itlbRepeater1 = PTWRepeater(frontend.io.ptw, fenceio.sfence, csrioIn.tlb)
397  val itlbRepeater2 = PTWRepeater(itlbRepeater1.io.ptw, ptw.io.tlb(0), fenceio.sfence, csrioIn.tlb)
398  val dtlbRepeater1  = PTWFilter(memBlock.io.ptw, fenceio.sfence, csrioIn.tlb, l2tlbParams.filterSize)
399  val dtlbRepeater2  = PTWRepeaterNB(passReady = false, dtlbRepeater1.io.ptw, ptw.io.tlb(1), fenceio.sfence, csrioIn.tlb)
400  ptw.io.sfence <> fenceio.sfence
401  ptw.io.csr.tlb <> csrioIn.tlb
402  ptw.io.csr.distribute_csr <> csrioIn.customCtrl.distribute_csr
403
404  // if l2 prefetcher use stream prefetch, it should be placed in XSCore
405  io.l2_pf_enable := csrioIn.customCtrl.l2_pf_enable
406
407  // Modules are reset one by one
408  val resetTree = ResetGenNode(
409    Seq(
410      ModuleNode(memBlock), ModuleNode(dtlbRepeater1),
411      ResetGenNode(Seq(
412        ModuleNode(itlbRepeater2),
413        ModuleNode(ptw),
414        ModuleNode(dtlbRepeater2),
415        ModuleNode(ptw_to_l2_buffer),
416      )),
417      ResetGenNode(Seq(
418        ModuleNode(exuBlocks.head),
419        ResetGenNode(
420          exuBlocks.tail.map(m => ModuleNode(m)) :+ ModuleNode(outer.wbArbiter.module)
421        ),
422        ResetGenNode(Seq(
423          ModuleNode(ctrlBlock),
424          ResetGenNode(Seq(
425            ModuleNode(frontend), ModuleNode(itlbRepeater1)
426          ))
427        ))
428      ))
429    )
430  )
431
432  ResetGen(resetTree, reset.asBool, !debugOpts.FPGAPlatform)
433
434}
435