xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision 6e3ea132be870a2e7573e122ef35630c7b184003)
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
18import xiangshan.mem._
19
20
21/** Backend Pipeline:
22  * Decode -> Rename -> Dispatch-1 -> Dispatch-2 -> Issue -> Exe
23  */
24class Backend(implicit val p: XSConfig) extends XSModule
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    val mem = Flipped(new MemToBackendIO)
31  })
32
33
34  val aluExeUnits = Array.tabulate(exuParameters.AluCnt)(_ => Module(new AluExeUnit))
35  val jmpExeUnit = Module(new JmpExeUnit)
36  val mulExeUnits = Array.tabulate(exuParameters.MulCnt)(_ => Module(new MulExeUnit))
37  val mduExeUnits = Array.tabulate(exuParameters.MduCnt)(_ => Module(new MulDivExeUnit))
38  //  val fmacExeUnits = Array.tabulate(exuParameters.FmacCnt)(_ => Module(new Fmac))
39  //  val fmiscExeUnits = Array.tabulate(exuParameters.FmiscCnt)(_ => Module(new Fmisc))
40  //  val fmiscDivSqrtExeUnits = Array.tabulate(exuParameters.FmiscDivSqrtCnt)(_ => Module(new FmiscDivSqrt))
41  val lsuExeUnits = Array.tabulate(exuParameters.StuCnt)(_ => Module(new LsExeUnit))
42  val exeUnits = jmpExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits ++ lsuExeUnits)
43  exeUnits.foreach(_.io.exception := DontCare)
44  exeUnits.foreach(_.io.dmem := DontCare)
45  exeUnits.foreach(_.io.mcommit := DontCare)
46
47  val decode = Module(new DecodeStage)
48  val brq = Module(new Brq)
49  val decBuf = Module(new DecodeBuffer)
50  val rename = Module(new Rename)
51  val dispatch = Module(new Dispatch(exeUnits.map(_.config)))
52  val roq = Module(new Roq)
53  val intRf = Module(new Regfile(
54    numReadPorts = NRReadPorts,
55    numWirtePorts = NRWritePorts,
56    hasZero = true
57  ))
58  val fpRf = Module(new Regfile(
59    numReadPorts = NRReadPorts,
60    numWirtePorts = NRWritePorts,
61    hasZero = false
62  ))
63
64  // backend redirect, flush pipeline
65  val redirect = Mux(roq.io.redirect.valid, roq.io.redirect, brq.io.redirect)
66
67  val redirectInfo = Wire(new RedirectInfo)
68  // exception or misprediction
69  redirectInfo.valid := roq.io.redirect.valid || brq.io.out.valid
70  redirectInfo.misPred := !roq.io.redirect.valid && brq.io.redirect.valid
71  redirectInfo.redirect := redirect.bits
72
73  var iqInfo = new StringBuilder
74  val issueQueues = exeUnits.zipWithIndex.map({ case (eu, i) =>
75    def needBypass(cfg: ExuConfig): Boolean = cfg.enableBypass
76
77    val bypassCnt = exeUnits.map(_.config).count(needBypass)
78    def needWakeup(cfg: ExuConfig): Boolean =
79      (cfg.readIntRf && cfg.writeIntRf) || (cfg.readFpRf && cfg.writeFpRf)
80
81    val wakeupCnt = exeUnits.map(_.config).count(needWakeup)
82    assert(!(needBypass(eu.config) && !needWakeup(eu.config))) // needBypass but dont needWakeup is not allowed
83    val iq = Module(new IssueQueue(
84      eu.config,
85      wakeupCnt,
86      bypassCnt,
87      eu.config.enableBypass,
88      fifo = eu.config.supportedFuncUnits.contains(FunctionUnit.lsuCfg)
89    ))
90    iq.io.redirect <> redirect
91    iq.io.numExist <> dispatch.io.numExist(i)
92    iq.io.enqCtrl <> dispatch.io.enqIQCtrl(i)
93    iq.io.enqData <> dispatch.io.enqIQData(i)
94    for(
95      (wakeUpPort, exuOut) <-
96      iq.io.wakeUpPorts.zip(exeUnits.filter(e => needWakeup(e.config)).map(_.io.out))
97    ){
98      wakeUpPort.bits := exuOut.bits
99      wakeUpPort.valid := exuOut.valid
100    }
101    iqInfo ++= {
102      s"[$i] ${eu.name} Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt" +
103        s" Supported Function:[" +
104        s"${
105          eu.config.supportedFuncUnits.map(
106            fu => FuType.functionNameMap(fu.fuType.litValue())).mkString(", "
107          )
108        }]\n"
109    }
110    eu.io.in <> iq.io.deq
111    eu.io.redirect <> redirect
112    iq
113  })
114
115  val bypassQueues = issueQueues.filter(_.enableBypass)
116  val bypassUnits = exeUnits.filter(_.config.enableBypass)
117  issueQueues.foreach(iq => {
118    for (i <- iq.io.bypassUops.indices) {
119      iq.io.bypassData(i).bits := bypassUnits(i).io.out.bits
120      iq.io.bypassData(i).valid := bypassUnits(i).io.out.valid
121    }
122    iq.io.bypassUops <> bypassQueues.map(_.io.selectedUop)
123  })
124
125  lsuExeUnits.foreach(_.io.dmem <> DontCare) // TODO
126  lsuExeUnits.foreach(_.io.mcommit <> roq.io.mcommit)
127  io.mem.mcommit := roq.io.mcommit
128  io.mem.ldin := DontCare // TODO
129  io.mem.stin := DontCare // TODO
130  jmpExeUnit.io.exception.valid := roq.io.redirect.valid
131  jmpExeUnit.io.exception.bits := roq.io.exception
132
133  io.frontend.redirectInfo <> redirectInfo
134  io.frontend.inOrderBrInfo <> brq.io.inOrderBrInfo
135
136  decode.io.in <> io.frontend.cfVec
137  brq.io.roqRedirect <> roq.io.redirect
138  brq.io.bcommit := roq.io.bcommit
139  brq.io.enqReqs <> decode.io.toBrq
140  for ((x, y) <- brq.io.exuRedirect.zip(exeUnits.filter(_.config.hasRedirect))) {
141    x.bits := y.io.out.bits
142    x.valid := y.io.out.fire() && y.io.out.bits.redirectValid
143  }
144  decode.io.brTags <> brq.io.brTags
145  decBuf.io.redirect <> redirect
146  decBuf.io.in <> decode.io.out
147
148  rename.io.redirect <> redirect
149  rename.io.roqCommits <> roq.io.commits
150  rename.io.in <> decBuf.io.out
151  rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr)
152  rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr)
153  rename.io.intPregRdy <> dispatch.io.intPregRdy
154  rename.io.fpPregRdy <> dispatch.io.fpPregRdy
155
156  dispatch.io.redirect <> redirect
157  dispatch.io.fromRename <> rename.io.out
158
159  roq.io.brqRedirect <> brq.io.redirect
160  roq.io.dp1Req <> dispatch.io.toRoq
161  dispatch.io.roqIdxs <> roq.io.roqIdxs
162  io.mem.dp1Req <> dispatch.io.toMoq
163  dispatch.io.moqIdxs <> io.mem.moqIdxs
164
165  intRf.io.readPorts <> dispatch.io.readIntRf
166  fpRf.io.readPorts <> dispatch.io.readFpRf
167
168  val exeWbReqs = exeUnits.map(_.io.out)
169
170  val wbIntIdx = exeUnits.zipWithIndex.filter(_._1.config.writeIntRf).map(_._2)
171  val wbFpIdx = exeUnits.zipWithIndex.filter(_._1.config.writeFpRf).map(_._2)
172
173  val wbu = Module(new Wbu(wbIntIdx, wbFpIdx))
174  wbu.io.in <> exeWbReqs
175
176  val wbIntResults = wbu.io.toIntRf
177  val wbFpResults = wbu.io.toFpRf
178
179  def exuOutToRfWrite(x: Valid[ExuOutput]): RfWritePort = {
180    val rfWrite = Wire(new RfWritePort)
181    rfWrite.wen := x.valid
182    rfWrite.addr := x.bits.uop.pdest
183    rfWrite.data := x.bits.data
184    rfWrite
185  }
186
187  intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite)
188  fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite)
189
190  rename.io.wbIntResults <> wbIntResults
191  rename.io.wbFpResults <> wbFpResults
192
193  roq.io.exeWbResults.take(exeWbReqs.length).zip(wbu.io.toRoq).foreach(x => x._1 := x._2)
194  roq.io.exeWbResults.last := brq.io.out
195
196
197  // TODO: Remove sink and source
198  val tmp = WireInit(0.U)
199  val sinks = Array[String](
200    "DTLBFINISH",
201    "DTLBPF",
202    "DTLBENABLE",
203    "perfCntCondMdcacheLoss",
204    "perfCntCondMl2cacheLoss",
205    "perfCntCondMdcacheHit",
206    "lsuMMIO",
207    "perfCntCondMl2cacheHit",
208    "perfCntCondMl2cacheReq",
209    "mtip",
210    "perfCntCondMdcacheReq",
211    "meip"
212  )
213  for (s <- sinks) {
214    BoringUtils.addSink(tmp, s)
215  }
216
217  val debugIntReg, debugFpReg = WireInit(VecInit(Seq.fill(32)(0.U(XLEN.W))))
218  BoringUtils.addSink(debugIntReg, "DEBUG_INT_ARCH_REG")
219  BoringUtils.addSink(debugFpReg, "DEBUG_FP_ARCH_REG")
220  val debugArchReg = WireInit(VecInit(debugIntReg ++ debugFpReg))
221  if (!p.FPGAPlatform) {
222    BoringUtils.addSource(debugArchReg, "difftestRegs")
223  }
224
225  print(iqInfo)
226
227}
228