xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision 4e12f40b2000d20984973eb847daa45fcab7abef)
1*4e12f40bSzhanglinjuan/***************************************************************************************
2*4e12f40bSzhanglinjuan* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3*4e12f40bSzhanglinjuan* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*4e12f40bSzhanglinjuan*
5*4e12f40bSzhanglinjuan* XiangShan is licensed under Mulan PSL v2.
6*4e12f40bSzhanglinjuan* You can use this software according to the terms and conditions of the Mulan PSL v2.
7*4e12f40bSzhanglinjuan* You may obtain a copy of Mulan PSL v2 at:
8*4e12f40bSzhanglinjuan*          http://license.coscl.org.cn/MulanPSL2
9*4e12f40bSzhanglinjuan*
10*4e12f40bSzhanglinjuan* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11*4e12f40bSzhanglinjuan* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12*4e12f40bSzhanglinjuan* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*4e12f40bSzhanglinjuan*
14*4e12f40bSzhanglinjuan* See the Mulan PSL v2 for more details.
15*4e12f40bSzhanglinjuan***************************************************************************************/
16*4e12f40bSzhanglinjuan
17*4e12f40bSzhanglinjuanpackage xiangshan.backend
18*4e12f40bSzhanglinjuan
19*4e12f40bSzhanglinjuanimport org.chipsalliance.cde.config.Parameters
20*4e12f40bSzhanglinjuanimport chisel3._
21*4e12f40bSzhanglinjuanimport chisel3.util._
22*4e12f40bSzhanglinjuanimport freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
23*4e12f40bSzhanglinjuanimport utils._
24*4e12f40bSzhanglinjuanimport utility._
25*4e12f40bSzhanglinjuanimport xiangshan._
26*4e12f40bSzhanglinjuanimport xiangshan.backend.exu._
27*4e12f40bSzhanglinjuanimport xiangshan.backend.fu._
28*4e12f40bSzhanglinjuanimport xiangshan.backend.rob._
29*4e12f40bSzhanglinjuanimport xiangshan.backend.dispatch._
30*4e12f40bSzhanglinjuanimport xiangshan.mem._
31*4e12f40bSzhanglinjuan
32*4e12f40bSzhanglinjuanclass FakeMemBlockWbSource()(implicit p: Parameters) extends LazyModule
33*4e12f40bSzhanglinjuan  with HasXSParameter with HasWritebackSource {
34*4e12f40bSzhanglinjuan  lazy val module = new FakeMemBlockWbSourceImp(this)
35*4e12f40bSzhanglinjuan
36*4e12f40bSzhanglinjuan  override val writebackSourceParams: Seq[WritebackSourceParams] = {
37*4e12f40bSzhanglinjuan    val params = new WritebackSourceParams
38*4e12f40bSzhanglinjuan    params.exuConfigs = (loadExuConfigs ++ storeExuConfigs).map(cfg => Seq(cfg))
39*4e12f40bSzhanglinjuan    Seq(params)
40*4e12f40bSzhanglinjuan  }
41*4e12f40bSzhanglinjuan  override lazy val writebackSourceImp: HasWritebackSourceImp = module
42*4e12f40bSzhanglinjuan}
43*4e12f40bSzhanglinjuan
44*4e12f40bSzhanglinjuanclass FakeMemBlockWbSourceImp(outer: FakeMemBlockWbSource) extends LazyModuleImp(outer)
45*4e12f40bSzhanglinjuan  with HasXSParameter
46*4e12f40bSzhanglinjuan  with HasWritebackSourceImp
47*4e12f40bSzhanglinjuan{
48*4e12f40bSzhanglinjuan  val io = IO(new Bundle() {
49*4e12f40bSzhanglinjuan    val in = Vec(exuParameters.LsExuCnt + exuParameters.StuCnt, Flipped(DecoupledIO(new ExuOutput)))
50*4e12f40bSzhanglinjuan    val out = Vec(exuParameters.LsExuCnt + exuParameters.StuCnt, DecoupledIO(new ExuOutput))
51*4e12f40bSzhanglinjuan  })
52*4e12f40bSzhanglinjuan  override def writebackSource1: Option[Seq[Seq[DecoupledIO[ExuOutput]]]] = Some(Seq(io.out))
53*4e12f40bSzhanglinjuan  io.out <> io.in
54*4e12f40bSzhanglinjuan}
55*4e12f40bSzhanglinjuan
56*4e12f40bSzhanglinjuan// Merge CtrlBlock, exuBlocks, wbArbiter, wb2Ctrl, etc into 1 module
57*4e12f40bSzhanglinjuanclass Backend(memWbSource: HasWritebackSource)(implicit p: Parameters) extends LazyModule
58*4e12f40bSzhanglinjuan  with HasXSParameter
59*4e12f40bSzhanglinjuan  with HasExuWbHelper
60*4e12f40bSzhanglinjuan{
61*4e12f40bSzhanglinjuan  val wbArbiter = LazyModule(new WbArbiterWrapper(exuConfigs, NRIntWritePorts, NRFpWritePorts))
62*4e12f40bSzhanglinjuan  val intWbPorts = wbArbiter.intWbPorts
63*4e12f40bSzhanglinjuan  val fpWbPorts = wbArbiter.fpWbPorts
64*4e12f40bSzhanglinjuan
65*4e12f40bSzhanglinjuan  // TODO: better RS organization
66*4e12f40bSzhanglinjuan  // generate rs according to number of function units
67*4e12f40bSzhanglinjuan  require(exuParameters.JmpCnt == 1)
68*4e12f40bSzhanglinjuan  require(exuParameters.MduCnt <= exuParameters.AluCnt && exuParameters.MduCnt > 0)
69*4e12f40bSzhanglinjuan  require(exuParameters.FmiscCnt <= exuParameters.FmacCnt && exuParameters.FmiscCnt > 0)
70*4e12f40bSzhanglinjuan  require(exuParameters.LduCnt == exuParameters.StuCnt) // TODO: remove this limitation
71*4e12f40bSzhanglinjuan
72*4e12f40bSzhanglinjuan  // one RS every 2 MDUs
73*4e12f40bSzhanglinjuan  val schedulePorts = Seq(
74*4e12f40bSzhanglinjuan    // exuCfg, numDeq, intFastWakeupTarget, fpFastWakeupTarget
75*4e12f40bSzhanglinjuan    Seq(
76*4e12f40bSzhanglinjuan      (AluExeUnitCfg, exuParameters.AluCnt, Seq(AluExeUnitCfg, LdExeUnitCfg, StaExeUnitCfg), Seq()),
77*4e12f40bSzhanglinjuan      (MulDivExeUnitCfg, exuParameters.MduCnt, Seq(AluExeUnitCfg, MulDivExeUnitCfg), Seq()),
78*4e12f40bSzhanglinjuan      (JumpCSRExeUnitCfg, 1, Seq(), Seq()),
79*4e12f40bSzhanglinjuan      (LdExeUnitCfg, exuParameters.LduCnt, Seq(AluExeUnitCfg, LdExeUnitCfg), Seq()),
80*4e12f40bSzhanglinjuan      (StaExeUnitCfg, exuParameters.StuCnt, Seq(), Seq()),
81*4e12f40bSzhanglinjuan      (StdExeUnitCfg, exuParameters.StuCnt, Seq(), Seq())
82*4e12f40bSzhanglinjuan    ),
83*4e12f40bSzhanglinjuan    Seq(
84*4e12f40bSzhanglinjuan      (FmacExeUnitCfg, exuParameters.FmacCnt, Seq(), Seq(FmacExeUnitCfg, FmiscExeUnitCfg)),
85*4e12f40bSzhanglinjuan      (FmiscExeUnitCfg, exuParameters.FmiscCnt, Seq(), Seq())
86*4e12f40bSzhanglinjuan    )
87*4e12f40bSzhanglinjuan  )
88*4e12f40bSzhanglinjuan
89*4e12f40bSzhanglinjuan  // should do outer fast wakeup ports here
90*4e12f40bSzhanglinjuan  val otherFastPorts = schedulePorts.zipWithIndex.map { case (sche, i) =>
91*4e12f40bSzhanglinjuan    val otherCfg = schedulePorts.zipWithIndex.filter(_._2 != i).map(_._1).reduce(_ ++ _)
92*4e12f40bSzhanglinjuan    val outerPorts = sche.map(cfg => {
93*4e12f40bSzhanglinjuan      // exe units from this scheduler need fastUops from exeunits
94*4e12f40bSzhanglinjuan      val outerWakeupInSche = sche.filter(_._1.wakeupFromExu)
95*4e12f40bSzhanglinjuan      val intraIntScheOuter = outerWakeupInSche.filter(_._3.contains(cfg._1)).map(_._1)
96*4e12f40bSzhanglinjuan      val intraFpScheOuter = outerWakeupInSche.filter(_._4.contains(cfg._1)).map(_._1)
97*4e12f40bSzhanglinjuan      // exe units from other schedulers need fastUop from outside
98*4e12f40bSzhanglinjuan      val otherIntSource = otherCfg.filter(_._3.contains(cfg._1)).map(_._1)
99*4e12f40bSzhanglinjuan      val otherFpSource = otherCfg.filter(_._4.contains(cfg._1)).map(_._1)
100*4e12f40bSzhanglinjuan      val intSource = findInWbPorts(intWbPorts, intraIntScheOuter ++ otherIntSource)
101*4e12f40bSzhanglinjuan      val fpSource = findInWbPorts(fpWbPorts, intraFpScheOuter ++ otherFpSource)
102*4e12f40bSzhanglinjuan      getFastWakeupIndex(cfg._1, intSource, fpSource, intWbPorts.length).sorted
103*4e12f40bSzhanglinjuan    })
104*4e12f40bSzhanglinjuan    println(s"inter-scheduler wakeup sources for $i: $outerPorts")
105*4e12f40bSzhanglinjuan    outerPorts
106*4e12f40bSzhanglinjuan  }
107*4e12f40bSzhanglinjuan
108*4e12f40bSzhanglinjuan  // allow mdu and fmisc to have 2*numDeq enqueue ports
109*4e12f40bSzhanglinjuan  val intDpPorts = (0 until exuParameters.AluCnt).map(i => {
110*4e12f40bSzhanglinjuan    if (i < exuParameters.JmpCnt) Seq((0, i), (1, i), (2, i))
111*4e12f40bSzhanglinjuan    else if (i < 2 * exuParameters.MduCnt) Seq((0, i), (1, i))
112*4e12f40bSzhanglinjuan    else Seq((0, i))
113*4e12f40bSzhanglinjuan  })
114*4e12f40bSzhanglinjuan  val lsDpPorts = (0 until exuParameters.LduCnt).map(i => Seq((3, i))) ++
115*4e12f40bSzhanglinjuan                  (0 until exuParameters.StuCnt).map(i => Seq((4, i))) ++
116*4e12f40bSzhanglinjuan                  (0 until exuParameters.StuCnt).map(i => Seq((5, i)))
117*4e12f40bSzhanglinjuan  val fpDpPorts = (0 until exuParameters.FmacCnt).map(i => {
118*4e12f40bSzhanglinjuan    if (i < 2 * exuParameters.FmiscCnt) Seq((0, i), (1, i))
119*4e12f40bSzhanglinjuan    else Seq((0, i))
120*4e12f40bSzhanglinjuan  })
121*4e12f40bSzhanglinjuan
122*4e12f40bSzhanglinjuan  val dispatchPorts = Seq(intDpPorts ++ lsDpPorts, fpDpPorts)
123*4e12f40bSzhanglinjuan
124*4e12f40bSzhanglinjuan  val outIntRfReadPorts = Seq(0, 0)
125*4e12f40bSzhanglinjuan  val outFpRfReadPorts = Seq(0, StorePipelineWidth)
126*4e12f40bSzhanglinjuan  val hasIntRf = Seq(true, false)
127*4e12f40bSzhanglinjuan  val hasFpRf = Seq(false, true)
128*4e12f40bSzhanglinjuan
129*4e12f40bSzhanglinjuan  val exuBlocks = schedulePorts.zip(dispatchPorts).zip(otherFastPorts).zipWithIndex.map {
130*4e12f40bSzhanglinjuan    case (((sche, disp), other), i) =>
131*4e12f40bSzhanglinjuan      LazyModule(new ExuBlock(sche, disp, intWbPorts, fpWbPorts, other, outIntRfReadPorts(i), outFpRfReadPorts(i), hasIntRf(i), hasFpRf(i)))
132*4e12f40bSzhanglinjuan  }
133*4e12f40bSzhanglinjuan
134*4e12f40bSzhanglinjuan  val fakeMemBlockWbSource = LazyModule(new FakeMemBlockWbSource())
135*4e12f40bSzhanglinjuan
136*4e12f40bSzhanglinjuan  val wb2Ctrl = LazyModule(new Wb2Ctrl(exuConfigs))
137*4e12f40bSzhanglinjuan  wb2Ctrl.addWritebackSink(exuBlocks :+ fakeMemBlockWbSource)
138*4e12f40bSzhanglinjuan  val dpExuConfigs = exuBlocks.flatMap(_.scheduler.dispatch2.map(_.configs))
139*4e12f40bSzhanglinjuan  val ctrlBlock = LazyModule(new CtrlBlock(dpExuConfigs))
140*4e12f40bSzhanglinjuan  val writebackSources = Seq(Seq(wb2Ctrl), Seq(wbArbiter))
141*4e12f40bSzhanglinjuan  writebackSources.foreach(s => ctrlBlock.addWritebackSink(s))
142*4e12f40bSzhanglinjuan
143*4e12f40bSzhanglinjuan  lazy val module = new BackendImp(this)
144*4e12f40bSzhanglinjuan}
145*4e12f40bSzhanglinjuan
146*4e12f40bSzhanglinjuanclass BackendImp(outer: Backend)(implicit p: Parameters) extends LazyModuleImp(outer)
147*4e12f40bSzhanglinjuan  with HasXSParameter
148*4e12f40bSzhanglinjuan{
149*4e12f40bSzhanglinjuan  val io = IO(new Bundle() {
150*4e12f40bSzhanglinjuan    val hartId = Input(UInt(64.W))
151*4e12f40bSzhanglinjuan    val cpu_halt = Output(Bool())
152*4e12f40bSzhanglinjuan
153*4e12f40bSzhanglinjuan    val memBlock = new Bundle() { // TODO: use class
154*4e12f40bSzhanglinjuan      val redirect = ValidIO(new Redirect)
155*4e12f40bSzhanglinjuan      val issue = Vec(exuParameters.LsExuCnt + exuParameters.StuCnt, DecoupledIO(new ExuInput))
156*4e12f40bSzhanglinjuan      val loadFastMatch = Vec(exuParameters.LduCnt, Output(UInt(exuParameters.LduCnt.W)))
157*4e12f40bSzhanglinjuan      val loadFastFuOpType = Vec(exuParameters.LduCnt, Output(FuOpType()))
158*4e12f40bSzhanglinjuan      val loadFastImm = Vec(exuParameters.LduCnt, Output(UInt(12.W)))
159*4e12f40bSzhanglinjuan      val rsfeedback = Vec(exuParameters.LsExuCnt, Flipped(new MemRSFeedbackIO()(p.alter((site, here, up) => {
160*4e12f40bSzhanglinjuan        case XSCoreParamsKey => up(XSCoreParamsKey).copy(
161*4e12f40bSzhanglinjuan          IssQueSize = IssQueSize * 2
162*4e12f40bSzhanglinjuan        )
163*4e12f40bSzhanglinjuan      }))))
164*4e12f40bSzhanglinjuan      val loadPc = Vec(exuParameters.LduCnt, Output(UInt(VAddrBits.W)))
165*4e12f40bSzhanglinjuan      val storePc = Vec(exuParameters.StuCnt, Output(UInt(VAddrBits.W)))
166*4e12f40bSzhanglinjuan      val stIssuePtr = Input(new SqPtr())
167*4e12f40bSzhanglinjuan      val writeback = Vec(exuParameters.LsExuCnt + exuParameters.StuCnt, Flipped(DecoupledIO(new ExuOutput)))
168*4e12f40bSzhanglinjuan      val s3_delayed_load_error = Vec(exuParameters.LduCnt, Input(Bool()))
169*4e12f40bSzhanglinjuan      val otherFastWakeup = Vec(exuParameters.LduCnt + 2 * exuParameters.StuCnt, Flipped(ValidIO(new MicroOp)))
170*4e12f40bSzhanglinjuan      val stIn = Vec(exuParameters.StuCnt, Flipped(ValidIO(new ExuInput)))
171*4e12f40bSzhanglinjuan      val memoryViolation = Flipped(ValidIO(new Redirect))
172*4e12f40bSzhanglinjuan      val sfence = Output(new SfenceBundle)
173*4e12f40bSzhanglinjuan      val tlbCsr = Output(new TlbCsrBundle)
174*4e12f40bSzhanglinjuan      val fenceToSbuffer = new FenceToSbuffer
175*4e12f40bSzhanglinjuan      val enqLsq = Flipped(new LsqEnqIO)
176*4e12f40bSzhanglinjuan      val lsqio = new Bundle {
177*4e12f40bSzhanglinjuan        val exceptionAddr = Flipped(new ExceptionAddrIO) // to csr
178*4e12f40bSzhanglinjuan        val rob = new RobLsqIO // rob to lsq
179*4e12f40bSzhanglinjuan        val lqCanAccept = Input(Bool())
180*4e12f40bSzhanglinjuan        val sqCanAccept = Input(Bool())
181*4e12f40bSzhanglinjuan      }
182*4e12f40bSzhanglinjuan      val csrCtrl = new CustomCSRCtrlIO
183*4e12f40bSzhanglinjuan      val lqCancelCnt = Input(UInt(log2Up(VirtualLoadQueueSize + 1).W))
184*4e12f40bSzhanglinjuan      val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W))
185*4e12f40bSzhanglinjuan      val scommit = Input(UInt(log2Ceil(EnsbufferWidth + 1).W))
186*4e12f40bSzhanglinjuan      val lcommit = Input(UInt(log2Up(CommitWidth + 1).W))
187*4e12f40bSzhanglinjuan      val debug_ls = Flipped(new DebugLSIO)
188*4e12f40bSzhanglinjuan      val lsTopdownInfo = Vec(exuParameters.LduCnt, Input(new LsTopdownInfo))
189*4e12f40bSzhanglinjuan    }
190*4e12f40bSzhanglinjuan
191*4e12f40bSzhanglinjuan    val frontend = new Bundle() { // TODO: use class
192*4e12f40bSzhanglinjuan      val frontend2Ctrl = Flipped(new FrontendToCtrlIO)
193*4e12f40bSzhanglinjuan      val sfence = Output(new SfenceBundle)
194*4e12f40bSzhanglinjuan      val tlbCsr = Output(new TlbCsrBundle)
195*4e12f40bSzhanglinjuan      val csrCtrl = Output(new CustomCSRCtrlIO)
196*4e12f40bSzhanglinjuan      val fencei = Output(Bool())
197*4e12f40bSzhanglinjuan    }
198*4e12f40bSzhanglinjuan
199*4e12f40bSzhanglinjuan    // CSR related
200*4e12f40bSzhanglinjuan    val perf = Input(new PerfCounterIO)
201*4e12f40bSzhanglinjuan    val externalInterrupt = new ExternalInterruptIO
202*4e12f40bSzhanglinjuan    val distributedUpdate = Vec(2, Flipped(new DistributedCSRUpdateReq))
203*4e12f40bSzhanglinjuan
204*4e12f40bSzhanglinjuan    val l2_pf_enable = Output(Bool())
205*4e12f40bSzhanglinjuan
206*4e12f40bSzhanglinjuan    val debugTopDown = new Bundle {
207*4e12f40bSzhanglinjuan      val fromRob = new RobCoreTopDownIO
208*4e12f40bSzhanglinjuan      val fromCore = new CoreDispatchTopDownIO
209*4e12f40bSzhanglinjuan    }
210*4e12f40bSzhanglinjuan    val debugRolling = new RobDebugRollingIO
211*4e12f40bSzhanglinjuan  })
212*4e12f40bSzhanglinjuan
213*4e12f40bSzhanglinjuan  private val ctrlBlock = outer.ctrlBlock.module
214*4e12f40bSzhanglinjuan  private val wb2Ctrl = outer.wb2Ctrl.module
215*4e12f40bSzhanglinjuan  private val exuBlocks = outer.exuBlocks.map(_.module)
216*4e12f40bSzhanglinjuan  private val wbArbiter = outer.wbArbiter.module
217*4e12f40bSzhanglinjuan
218*4e12f40bSzhanglinjuan  val mem = io.memBlock
219*4e12f40bSzhanglinjuan  val frontend = io.frontend
220*4e12f40bSzhanglinjuan
221*4e12f40bSzhanglinjuan  outer.fakeMemBlockWbSource.module.io.in <> mem.writeback
222*4e12f40bSzhanglinjuan
223*4e12f40bSzhanglinjuan  ctrlBlock.io.hartId := io.hartId
224*4e12f40bSzhanglinjuan  exuBlocks.foreach(_.io.hartId := io.hartId)
225*4e12f40bSzhanglinjuan  wbArbiter.io.hartId := io.hartId
226*4e12f40bSzhanglinjuan
227*4e12f40bSzhanglinjuan  io.cpu_halt := ctrlBlock.io.cpu_halt
228*4e12f40bSzhanglinjuan
229*4e12f40bSzhanglinjuan  wbArbiter.io.redirect <> ctrlBlock.io.redirect
230*4e12f40bSzhanglinjuan
231*4e12f40bSzhanglinjuan  val allWriteback = exuBlocks.flatMap(_.io.fuWriteback) ++ outer.fakeMemBlockWbSource.module.io.out
232*4e12f40bSzhanglinjuan  require(exuConfigs.length == allWriteback.length, s"${exuConfigs.length} != ${allWriteback.length}")
233*4e12f40bSzhanglinjuan  wbArbiter.io.in <> allWriteback
234*4e12f40bSzhanglinjuan  val rfWriteback = wbArbiter.io.out
235*4e12f40bSzhanglinjuan
236*4e12f40bSzhanglinjuan  // memblock error exception writeback, 1 cycle after normal writeback
237*4e12f40bSzhanglinjuan  wb2Ctrl.io.s3_delayed_load_error <> mem.s3_delayed_load_error
238*4e12f40bSzhanglinjuan
239*4e12f40bSzhanglinjuan  wb2Ctrl.io.redirect <> ctrlBlock.io.redirect
240*4e12f40bSzhanglinjuan  outer.wb2Ctrl.generateWritebackIO()
241*4e12f40bSzhanglinjuan
242*4e12f40bSzhanglinjuan  require(exuBlocks.count(_.fuConfigs.map(_._1).contains(JumpCSRExeUnitCfg)) == 1)
243*4e12f40bSzhanglinjuan  val csrFenceMod = exuBlocks.filter(_.fuConfigs.map(_._1).contains(JumpCSRExeUnitCfg)).head
244*4e12f40bSzhanglinjuan  val csrioIn = csrFenceMod.io.fuExtra.csrio.get
245*4e12f40bSzhanglinjuan  val fenceio = csrFenceMod.io.fuExtra.fenceio.get
246*4e12f40bSzhanglinjuan
247*4e12f40bSzhanglinjuan  ctrlBlock.io.frontend <> frontend.frontend2Ctrl
248*4e12f40bSzhanglinjuan  frontend.sfence <> fenceio.sfence
249*4e12f40bSzhanglinjuan  frontend.tlbCsr <> csrioIn.tlb
250*4e12f40bSzhanglinjuan  frontend.csrCtrl <> csrioIn.customCtrl
251*4e12f40bSzhanglinjuan  frontend.fencei := fenceio.fencei
252*4e12f40bSzhanglinjuan
253*4e12f40bSzhanglinjuan  ctrlBlock.io.csrCtrl <> csrioIn.customCtrl
254*4e12f40bSzhanglinjuan  val redirectBlocks = exuBlocks.reverse.filter(_.fuConfigs.map(_._1).map(_.hasRedirect).reduce(_ || _))
255*4e12f40bSzhanglinjuan  ctrlBlock.io.exuRedirect <> redirectBlocks.flatMap(_.io.fuExtra.exuRedirect)
256*4e12f40bSzhanglinjuan  ctrlBlock.io.stIn <> mem.stIn
257*4e12f40bSzhanglinjuan  ctrlBlock.io.memoryViolation <> mem.memoryViolation
258*4e12f40bSzhanglinjuan  exuBlocks.head.io.scheExtra.enqLsq.get <> mem.enqLsq
259*4e12f40bSzhanglinjuan  exuBlocks.foreach(b => {
260*4e12f40bSzhanglinjuan    b.io.scheExtra.lcommit := mem.lcommit
261*4e12f40bSzhanglinjuan    b.io.scheExtra.scommit := mem.scommit
262*4e12f40bSzhanglinjuan    b.io.scheExtra.lqCancelCnt := mem.lqCancelCnt
263*4e12f40bSzhanglinjuan    b.io.scheExtra.sqCancelCnt := mem.sqCancelCnt
264*4e12f40bSzhanglinjuan  })
265*4e12f40bSzhanglinjuan  val sourceModules = outer.writebackSources.map(_.map(_.module.asInstanceOf[HasWritebackSourceImp]))
266*4e12f40bSzhanglinjuan  outer.ctrlBlock.generateWritebackIO()
267*4e12f40bSzhanglinjuan
268*4e12f40bSzhanglinjuan  val allFastUop = exuBlocks.flatMap(b => b.io.fastUopOut.dropRight(b.numOutFu)) ++ mem.otherFastWakeup
269*4e12f40bSzhanglinjuan  require(allFastUop.length == exuConfigs.length, s"${allFastUop.length} != ${exuConfigs.length}")
270*4e12f40bSzhanglinjuan  val intFastUop = allFastUop.zip(exuConfigs).filter(_._2.writeIntRf).map(_._1)
271*4e12f40bSzhanglinjuan  val fpFastUop = allFastUop.zip(exuConfigs).filter(_._2.writeFpRf).map(_._1)
272*4e12f40bSzhanglinjuan  val intFastUop1 = outer.wbArbiter.intConnections.map(c => intFastUop(c.head))
273*4e12f40bSzhanglinjuan  val fpFastUop1 = outer.wbArbiter.fpConnections.map(c => fpFastUop(c.head))
274*4e12f40bSzhanglinjuan  val allFastUop1 = intFastUop1 ++ fpFastUop1
275*4e12f40bSzhanglinjuan
276*4e12f40bSzhanglinjuan  ctrlBlock.io.dispatch <> exuBlocks.flatMap(_.io.in)
277*4e12f40bSzhanglinjuan  ctrlBlock.io.rsReady := exuBlocks.flatMap(_.io.scheExtra.rsReady)
278*4e12f40bSzhanglinjuan  ctrlBlock.io.enqLsq <> mem.enqLsq
279*4e12f40bSzhanglinjuan  ctrlBlock.io.lqDeq := mem.lcommit
280*4e12f40bSzhanglinjuan  ctrlBlock.io.sqDeq := mem.scommit
281*4e12f40bSzhanglinjuan  ctrlBlock.io.lqCanAccept := mem.lsqio.lqCanAccept
282*4e12f40bSzhanglinjuan  ctrlBlock.io.sqCanAccept := mem.lsqio.sqCanAccept
283*4e12f40bSzhanglinjuan  ctrlBlock.io.lqCancelCnt := mem.lqCancelCnt
284*4e12f40bSzhanglinjuan  ctrlBlock.io.sqCancelCnt := mem.sqCancelCnt
285*4e12f40bSzhanglinjuan  ctrlBlock.io.robHeadLsIssue := exuBlocks.map(_.io.scheExtra.robHeadLsIssue).reduce(_ || _)
286*4e12f40bSzhanglinjuan
287*4e12f40bSzhanglinjuan  exuBlocks(0).io.scheExtra.fpRfReadIn.get <> exuBlocks(1).io.scheExtra.fpRfReadOut.get
288*4e12f40bSzhanglinjuan  exuBlocks(0).io.scheExtra.fpStateReadIn.get <> exuBlocks(1).io.scheExtra.fpStateReadOut.get
289*4e12f40bSzhanglinjuan
290*4e12f40bSzhanglinjuan  for((c, e) <- ctrlBlock.io.ld_pc_read.zip(exuBlocks(0).io.issue.get)){
291*4e12f40bSzhanglinjuan    // read load pc at load s0
292*4e12f40bSzhanglinjuan    c.ptr := e.bits.uop.cf.ftqPtr
293*4e12f40bSzhanglinjuan    c.offset := e.bits.uop.cf.ftqOffset
294*4e12f40bSzhanglinjuan  }
295*4e12f40bSzhanglinjuan  // return load pc at load s2
296*4e12f40bSzhanglinjuan  mem.loadPc <> VecInit(ctrlBlock.io.ld_pc_read.map(_.data))
297*4e12f40bSzhanglinjuan
298*4e12f40bSzhanglinjuan  for((c, e) <- ctrlBlock.io.st_pc_read.zip(exuBlocks(0).io.issue.get.drop(exuParameters.LduCnt))){
299*4e12f40bSzhanglinjuan    // read store pc at store s0
300*4e12f40bSzhanglinjuan    c.ptr := e.bits.uop.cf.ftqPtr
301*4e12f40bSzhanglinjuan    c.offset := e.bits.uop.cf.ftqOffset
302*4e12f40bSzhanglinjuan  }
303*4e12f40bSzhanglinjuan  // return store pc at store s2
304*4e12f40bSzhanglinjuan  mem.storePc <> VecInit(ctrlBlock.io.st_pc_read.map(_.data))
305*4e12f40bSzhanglinjuan
306*4e12f40bSzhanglinjuan  mem.issue <> exuBlocks(0).io.issue.get
307*4e12f40bSzhanglinjuan  // By default, instructions do not have exceptions when they enter the function units.
308*4e12f40bSzhanglinjuan  mem.issue.map(_.bits.uop.clearExceptions())
309*4e12f40bSzhanglinjuan  exuBlocks(0).io.scheExtra.loadFastMatch.get <> mem.loadFastMatch
310*4e12f40bSzhanglinjuan  exuBlocks(0).io.scheExtra.loadFastFuOpType.get <> mem.loadFastFuOpType
311*4e12f40bSzhanglinjuan  exuBlocks(0).io.scheExtra.loadFastImm.get <> mem.loadFastImm
312*4e12f40bSzhanglinjuan
313*4e12f40bSzhanglinjuan  val stdIssue = exuBlocks(0).io.issue.get.takeRight(exuParameters.StuCnt)
314*4e12f40bSzhanglinjuan  exuBlocks.map(_.io).foreach { exu =>
315*4e12f40bSzhanglinjuan    exu.redirect <> ctrlBlock.io.redirect
316*4e12f40bSzhanglinjuan    exu.allocPregs <> ctrlBlock.io.allocPregs
317*4e12f40bSzhanglinjuan    exu.rfWriteback <> rfWriteback
318*4e12f40bSzhanglinjuan    exu.fastUopIn <> allFastUop1
319*4e12f40bSzhanglinjuan    exu.scheExtra.jumpPc <> ctrlBlock.io.jumpPc
320*4e12f40bSzhanglinjuan    exu.scheExtra.jalr_target <> ctrlBlock.io.jalr_target
321*4e12f40bSzhanglinjuan    exu.scheExtra.stIssuePtr <> mem.stIssuePtr
322*4e12f40bSzhanglinjuan    exu.scheExtra.debug_fp_rat <> ctrlBlock.io.debug_fp_rat
323*4e12f40bSzhanglinjuan    exu.scheExtra.debug_int_rat <> ctrlBlock.io.debug_int_rat
324*4e12f40bSzhanglinjuan    exu.scheExtra.robDeqPtr := ctrlBlock.io.robDeqPtr
325*4e12f40bSzhanglinjuan    exu.scheExtra.memWaitUpdateReq.staIssue.zip(mem.stIn).foreach{case (sink, src) => {
326*4e12f40bSzhanglinjuan      sink.bits := src.bits
327*4e12f40bSzhanglinjuan      sink.valid := src.valid
328*4e12f40bSzhanglinjuan    }}
329*4e12f40bSzhanglinjuan    exu.scheExtra.memWaitUpdateReq.stdIssue.zip(stdIssue).foreach{case (sink, src) => {
330*4e12f40bSzhanglinjuan      sink.valid := src.valid
331*4e12f40bSzhanglinjuan      sink.bits := src.bits
332*4e12f40bSzhanglinjuan    }}
333*4e12f40bSzhanglinjuan  }
334*4e12f40bSzhanglinjuan
335*4e12f40bSzhanglinjuan  XSPerfHistogram("fastIn_count", PopCount(allFastUop1.map(_.valid)), true.B, 0, allFastUop1.length, 1)
336*4e12f40bSzhanglinjuan  XSPerfHistogram("wakeup_count", PopCount(rfWriteback.map(_.valid)), true.B, 0, rfWriteback.length, 1)
337*4e12f40bSzhanglinjuan
338*4e12f40bSzhanglinjuan  ctrlBlock.perfinfo.perfEventsEu0 := exuBlocks(0).getPerf.dropRight(outer.exuBlocks(0).scheduler.numRs)
339*4e12f40bSzhanglinjuan  ctrlBlock.perfinfo.perfEventsEu1 := exuBlocks(1).getPerf.dropRight(outer.exuBlocks(1).scheduler.numRs)
340*4e12f40bSzhanglinjuan  ctrlBlock.perfinfo.perfEventsRs  := outer.exuBlocks.flatMap(b => b.module.getPerf.takeRight(b.scheduler.numRs))
341*4e12f40bSzhanglinjuan
342*4e12f40bSzhanglinjuan  csrioIn.hartId <> io.hartId
343*4e12f40bSzhanglinjuan
344*4e12f40bSzhanglinjuan  val perf = WireInit(io.perf) // other perf events are assigned outside the backend
345*4e12f40bSzhanglinjuan  perf.retiredInstr <> ctrlBlock.io.robio.toCSR.perfinfo.retiredInstr
346*4e12f40bSzhanglinjuan  perf.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo
347*4e12f40bSzhanglinjuan  perf.perfEventsCtrl <> ctrlBlock.getPerf
348*4e12f40bSzhanglinjuan  csrioIn.perf <> perf
349*4e12f40bSzhanglinjuan
350*4e12f40bSzhanglinjuan  csrioIn.fpu.fflags <> ctrlBlock.io.robio.toCSR.fflags
351*4e12f40bSzhanglinjuan  csrioIn.fpu.isIllegal := false.B
352*4e12f40bSzhanglinjuan  csrioIn.fpu.dirty_fs <> ctrlBlock.io.robio.toCSR.dirty_fs
353*4e12f40bSzhanglinjuan  csrioIn.fpu.frm <> exuBlocks(1).io.fuExtra.frm.get
354*4e12f40bSzhanglinjuan  csrioIn.exception <> ctrlBlock.io.robio.exception
355*4e12f40bSzhanglinjuan  csrioIn.isXRet <> ctrlBlock.io.robio.toCSR.isXRet
356*4e12f40bSzhanglinjuan  csrioIn.trapTarget <> ctrlBlock.io.robio.toCSR.trapTarget
357*4e12f40bSzhanglinjuan  csrioIn.interrupt <> ctrlBlock.io.robio.toCSR.intrBitSet
358*4e12f40bSzhanglinjuan  csrioIn.wfi_event <> ctrlBlock.io.robio.toCSR.wfiEvent
359*4e12f40bSzhanglinjuan  csrioIn.memExceptionVAddr <> mem.lsqio.exceptionAddr.vaddr
360*4e12f40bSzhanglinjuan
361*4e12f40bSzhanglinjuan  csrioIn.externalInterrupt := io.externalInterrupt
362*4e12f40bSzhanglinjuan
363*4e12f40bSzhanglinjuan  csrioIn.distributedUpdate := io.distributedUpdate
364*4e12f40bSzhanglinjuan
365*4e12f40bSzhanglinjuan  mem.sfence <> fenceio.sfence
366*4e12f40bSzhanglinjuan  mem.fenceToSbuffer <> fenceio.sbuffer
367*4e12f40bSzhanglinjuan
368*4e12f40bSzhanglinjuan  mem.redirect <> ctrlBlock.io.redirect
369*4e12f40bSzhanglinjuan  mem.rsfeedback <> exuBlocks(0).io.scheExtra.feedback.get
370*4e12f40bSzhanglinjuan  mem.csrCtrl <> csrioIn.customCtrl
371*4e12f40bSzhanglinjuan  mem.tlbCsr <> csrioIn.tlb
372*4e12f40bSzhanglinjuan  mem.lsqio.rob <> ctrlBlock.io.robio.lsq
373*4e12f40bSzhanglinjuan  mem.lsqio.exceptionAddr.isStore := CommitType.lsInstIsStore(ctrlBlock.io.robio.exception.bits.uop.ctrl.commitType)
374*4e12f40bSzhanglinjuan  mem.debug_ls <> ctrlBlock.io.robio.debug_ls
375*4e12f40bSzhanglinjuan  mem.lsTopdownInfo <> ctrlBlock.io.robio.lsTopdownInfo
376*4e12f40bSzhanglinjuan
377*4e12f40bSzhanglinjuan  // if l2 prefetcher use stream prefetch, it should be placed in XSCore
378*4e12f40bSzhanglinjuan  io.l2_pf_enable := csrioIn.customCtrl.l2_pf_enable
379*4e12f40bSzhanglinjuan
380*4e12f40bSzhanglinjuan  io.debugTopDown.fromRob := ctrlBlock.io.debugTopDown.fromRob
381*4e12f40bSzhanglinjuan  ctrlBlock.io.debugTopDown.fromCore := io.debugTopDown.fromCore
382*4e12f40bSzhanglinjuan  io.debugRolling := ctrlBlock.io.debugRolling
383*4e12f40bSzhanglinjuan
384*4e12f40bSzhanglinjuan  val resetTree = ResetGenNode(
385*4e12f40bSzhanglinjuan    exuBlocks.tail.map(m => ModuleNode(m))
386*4e12f40bSzhanglinjuan      :+ ModuleNode(wbArbiter)
387*4e12f40bSzhanglinjuan      :+ ModuleNode(ctrlBlock)
388*4e12f40bSzhanglinjuan  )
389*4e12f40bSzhanglinjuan  ResetGen(resetTree, reset, !p(DebugOptionsKey).FPGAPlatform)
390*4e12f40bSzhanglinjuan}
391