xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision 0b2a9073a586ead47dbd26e87b67dcb8e4573f68)
1package xiangshan.backend
2
3import bus.simplebus.SimpleBusUC
4import chisel3._
5import chisel3.util._
6import chisel3.util.experimental.BoringUtils
7import noop.MemMMUIO
8import xiangshan._
9import xiangshan.backend.decode.{DecodeBuffer, DecodeStage}
10import xiangshan.backend.rename.Rename
11import xiangshan.backend.brq.Brq
12import xiangshan.backend.dispatch.Dispatch
13import xiangshan.backend.exu._
14import xiangshan.backend.fu.FunctionUnit
15import xiangshan.backend.issue.IssueQueue
16import xiangshan.backend.regfile.{Regfile, RfWritePort}
17import xiangshan.backend.roq.Roq
18
19
20/** Backend Pipeline:
21  * Decode -> Rename -> Dispatch-1 -> Dispatch-2 -> Issue -> Exe
22  */
23class Backend(implicit val p: XSConfig) extends XSModule
24  with HasExeUnits
25  with NeedImpl {
26  val io = IO(new Bundle {
27    val dmem = new SimpleBusUC(addrBits = VAddrBits)
28    val memMMU = Flipped(new MemMMUIO)
29    val frontend = Flipped(new FrontendToBackendIO)
30  })
31
32
33  val decode = Module(new DecodeStage)
34  val brq = Module(new Brq)
35  val decBuf = Module(new DecodeBuffer)
36  val rename = Module(new Rename)
37  val dispatch = Module(new Dispatch(exeUnits.map(_.config)))
38  val roq = Module(new Roq)
39  val intRf = Module(new Regfile(
40    numReadPorts = NRReadPorts,
41    numWirtePorts = NRWritePorts,
42    hasZero = true
43  ))
44  val fpRf = Module(new Regfile(
45    numReadPorts = NRReadPorts,
46    numWirtePorts = NRWritePorts,
47    hasZero = false
48  ))
49
50  // backend redirect, flush pipeline
51  val redirect = Mux(roq.io.redirect.valid, roq.io.redirect, brq.io.redirect)
52
53  val redirectInfo = Wire(new RedirectInfo)
54  // exception or misprediction
55  redirectInfo.valid := roq.io.redirect.valid || brq.io.out.valid
56  redirectInfo.misPred := !roq.io.redirect.valid && brq.io.redirect.valid
57  redirectInfo.redirect := redirect.bits
58
59  val issueQueues = exeUnits.zipWithIndex.map({ case (eu, i) =>
60    def needBypass(cfg: ExuConfig): Boolean = cfg.enableBypass
61
62    val bypassCnt = if(eu.config.enableBypass) exeUnits.map(_.config).count(needBypass) else 0
63    def needWakeup(cfg: ExuConfig): Boolean =
64      (cfg.readIntRf && cfg.writeIntRf) || (cfg.readFpRf && cfg.writeFpRf)
65
66    val wakeupCnt = exeUnits.map(_.config).count(needWakeup)
67    assert(!(needBypass(eu.config) && !needWakeup(eu.config))) // needBypass but dont needWakeup is not allowed
68    val iq = Module(new IssueQueue(
69      eu.config,
70      wakeupCnt,
71      bypassCnt,
72      fifo = eu.config.supportedFuncUnits.contains(FunctionUnit.lsuCfg)
73    ))
74    iq.io.redirect <> redirect
75    iq.io.numExist <> dispatch.io.numExist(i)
76    iq.io.enqCtrl <> dispatch.io.enqIQCtrl(i)
77    iq.io.enqData <> dispatch.io.enqIQData(i)
78    val wuUnitsOut = exeUnits.filter(e => needWakeup(e.config)).map(_.io.out)
79    for (i <- iq.io.wakeUpPorts.indices) {
80      iq.io.wakeUpPorts(i).bits <> wuUnitsOut(i).bits
81      iq.io.wakeUpPorts(i).valid := wuUnitsOut(i).valid
82    }
83    println(
84      s"[$i] ${eu.name} Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt" +
85        s" Supported Function:[" +
86        s"${
87          eu.config.supportedFuncUnits.map(
88            fu => FuType.functionNameMap(fu.fuType.litValue())).mkString(", "
89          )
90        }]"
91    )
92    eu.io.in <> iq.io.deq
93    eu.io.redirect <> redirect
94    iq
95  })
96
97  val bypassQueues = issueQueues.filter(_.bypassCnt > 0)
98  val bypassUnits = exeUnits.filter(_.config.enableBypass)
99  bypassQueues.foreach(iq => {
100    for (i <- iq.io.bypassUops.indices) {
101      iq.io.bypassData(i).bits := bypassUnits(i).io.out.bits
102      iq.io.bypassData(i).valid := bypassUnits(i).io.out.valid
103    }
104    iq.io.bypassUops <> bypassQueues.map(_.io.selectedUop)
105  })
106
107  lsuExeUnits.foreach(_.io.dmem <> io.dmem)
108  lsuExeUnits.foreach(_.io.scommit <> roq.io.scommit)
109
110  io.frontend.redirectInfo <> redirectInfo
111  io.frontend.commits <> roq.io.commits
112
113  decode.io.in <> io.frontend.cfVec
114  brq.io.roqRedirect <> roq.io.redirect
115  brq.io.enqReqs <> decode.io.toBrq
116  for ((x, y) <- brq.io.exuRedirect.zip(exeUnits.filter(_.config.hasRedirect))) {
117    x.bits := y.io.out.bits
118    x.valid := y.io.out.fire() && y.io.out.bits.redirectValid
119  }
120  decode.io.brTags <> brq.io.brTags
121  decBuf.io.redirect <> redirect
122  decBuf.io.in <> decode.io.out
123
124  rename.io.redirect <> redirect
125  rename.io.roqCommits <> roq.io.commits
126  rename.io.in <> decBuf.io.out
127  rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr)
128  rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr)
129  rename.io.intPregRdy <> dispatch.io.intPregRdy
130  rename.io.fpPregRdy <> dispatch.io.fpPregRdy
131
132  dispatch.io.redirect <> redirect
133  dispatch.io.fromRename <> rename.io.out
134
135  roq.io.brqRedirect <> brq.io.redirect
136  roq.io.dp1Req <> dispatch.io.toRoq
137  dispatch.io.roqIdxs <> roq.io.roqIdxs
138  dispatch.io.roqIsEmpty := roq.io.roqIsEmpty
139  dispatch.io.isNoSpecExecCommit := roq.io.commits.head.valid
140
141  intRf.io.readPorts <> dispatch.io.readIntRf
142  fpRf.io.readPorts <> dispatch.io.readFpRf
143
144  val exeWbReqs = exeUnits.map(_.io.out)
145
146  val wbIntIdx = exeUnits.zipWithIndex.filter(_._1.config.writeIntRf).map(_._2)
147  val wbFpIdx = exeUnits.zipWithIndex.filter(_._1.config.writeFpRf).map(_._2)
148
149  val wbu = Module(new Wbu(wbIntIdx, wbFpIdx))
150  wbu.io.in <> exeWbReqs
151
152  val wbIntResults = wbu.io.toIntRf
153  val wbFpResults = wbu.io.toFpRf
154
155  def exuOutToRfWrite(x: Valid[ExuOutput]): RfWritePort = {
156    val rfWrite = Wire(new RfWritePort)
157    rfWrite.wen := x.valid
158    rfWrite.addr := x.bits.uop.pdest
159    rfWrite.data := x.bits.data
160    rfWrite
161  }
162
163  intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite)
164  fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite)
165
166  rename.io.wbIntResults <> wbIntResults
167  rename.io.wbFpResults <> wbFpResults
168
169  roq.io.exeWbResults.take(exeWbReqs.length).zip(wbu.io.toRoq).foreach(x => x._1 := x._2)
170  roq.io.exeWbResults.last := brq.io.out
171
172
173  // TODO: Remove sink and source
174  val tmp = WireInit(0.U)
175  val sinks = Array[String](
176    "DTLBFINISH",
177    "DTLBPF",
178    "DTLBENABLE",
179    "perfCntCondMdcacheLoss",
180    "perfCntCondMl2cacheLoss",
181    "perfCntCondMdcacheHit",
182    "lsuMMIO",
183    "perfCntCondMl2cacheHit",
184    "perfCntCondMl2cacheReq",
185    "mtip",
186    "perfCntCondMdcacheReq",
187    "meip"
188  )
189  for (s <- sinks) {
190    BoringUtils.addSink(tmp, s)
191  }
192
193  val debugIntReg, debugFpReg = WireInit(VecInit(Seq.fill(32)(0.U(XLEN.W))))
194  BoringUtils.addSink(debugIntReg, "DEBUG_INT_ARCH_REG")
195  BoringUtils.addSink(debugFpReg, "DEBUG_FP_ARCH_REG")
196  val debugArchReg = WireInit(VecInit(debugIntReg ++ debugFpReg))
197  if (!p.FPGAPlatform) {
198    BoringUtils.addSource(debugArchReg, "difftestRegs")
199  }
200
201}
202