xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision a9d430a1434db1cf5b3df8effae82f3432f3fbed)
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.issue.IssueQueue
15import xiangshan.backend.regfile.{Regfile, RfWritePort}
16import xiangshan.backend.roq.Roq
17
18
19/** Backend Pipeline:
20  * Decode -> Rename -> Dispatch-1 -> Dispatch-2 -> Issue -> Exe
21  */
22class Backend(implicit val p: XSConfig) extends XSModule
23  with HasExeUnits
24  with NeedImpl
25{
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)
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  val redirect = Mux(roq.io.redirect.valid, roq.io.redirect, brq.io.redirect)
50  val issueQueues = exeUnits.zipWithIndex.map({ case(eu, i) =>
51    def needWakeup(x: Exu): Boolean = (eu.readIntRf && x.writeIntRf) || (eu.readFpRf && x.writeFpRf)
52    val wakeupCnt = exeUnits.count(needWakeup)
53    val bypassCnt = if(eu.fuTypeInt == FuType.alu.litValue()) exuConfig.AluCnt else 0
54    val iq = Module(new IssueQueue(eu.fuTypeInt, wakeupCnt, bypassCnt))
55    iq.io.redirect <> redirect
56    iq.io.enqCtrl <> dispatch.io.enqIQCtrl(i)
57    iq.io.enqData <> dispatch.io.enqIQData(i)
58    iq.io.wakeUpPorts <> exeUnits.filter(needWakeup).map(_.io.out)
59    println(s"[$i] $eu Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt")
60    eu.io.in <> iq.io.deq
61    eu.io.redirect <> redirect
62    iq
63  })
64
65  val aluQueues = issueQueues.filter(_.fuTypeInt == FuType.alu.litValue())
66  aluQueues.foreach(aluQ => {
67    aluQ.io.bypassUops <> aluQueues.map(_.io.selectedUop)
68    aluQ.io.bypassData <> aluExeUnits.map(_.io.out)
69  })
70
71  lsuExeUnits.foreach(_.io.dmem <> io.dmem)
72
73  io.frontend.redirect <> redirect
74  io.frontend.commits <> roq.io.commits
75
76  decode.io.in <> io.frontend.cfVec
77  brq.io.roqRedirect <> roq.io.redirect
78  brq.io.enqReqs <> decode.io.toBrq
79  for(i <- bjUnits.indices){
80    brq.io.exuRedirect(i).bits := bjUnits(i).io.out.bits
81    brq.io.exuRedirect(i).valid := bjUnits(i).io.out.fire()
82  }
83  decode.io.brMasks <> brq.io.brMasks
84  decode.io.brTags <> brq.io.brTags
85  decBuf.io.in <> decode.io.out
86
87  rename.io.redirect <> redirect
88  rename.io.roqCommits <> roq.io.commits
89  rename.io.in <> decBuf.io.out
90  rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr)
91  rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr)
92  rename.io.intPregRdy <> dispatch.io.intPregRdy
93  rename.io.fpPregRdy <> dispatch.io.fpPregRdy
94
95  dispatch.io.redirect <> redirect
96  dispatch.io.fromRename <> rename.io.out
97
98  roq.io.brqRedirect <> brq.io.redirect
99  roq.io.dp1Req <> dispatch.io.toRoq
100  dispatch.io.roqIdxs <> roq.io.roqIdxs
101
102  intRf.io.readPorts <> dispatch.io.readIntRf
103  fpRf.io.readPorts <> dispatch.io.readFpRf
104
105  val exeWbReqs = exeUnits.map(_.io.out)
106  val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits)).map(_.io.out)
107  val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out)
108  val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts))
109  val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts))
110  val wbIntResults = intWbArb.io.out
111  val wbFpResults = fpWbArb.io.out
112
113  def exuOutToRfWrite(x: Valid[ExuOutput]) = {
114    val rfWrite = Wire(new RfWritePort)
115    rfWrite.wen := x.valid
116    rfWrite.addr := x.bits.uop.pdest
117    rfWrite.data := x.bits.data
118    rfWrite
119  }
120
121  intWbArb.io.in <> wbIntReqs
122  intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite)
123
124  fpWbArb.io.in <> wbFpReqs
125  fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite)
126
127  rename.io.wbIntResults <> wbIntResults
128  rename.io.wbFpResults <> wbFpResults
129
130  roq.io.exeWbResults.zip(exeWbReqs).foreach({case (x,y) => {
131    x.bits := y.bits
132    x.valid := y.fire()
133  }})
134
135
136  // TODO: Remove sink and source
137  val tmp = WireInit(0.U)
138  val sinks = Array[String](
139    "DTLBFINISH",
140    "DTLBPF",
141    "DTLBENABLE",
142    "perfCntCondMdcacheLoss",
143    "perfCntCondMl2cacheLoss",
144    "perfCntCondMdcacheHit",
145    "lsuMMIO",
146    "perfCntCondMl2cacheHit",
147    "perfCntCondMl2cacheReq",
148    "mtip",
149    "perfCntCondMdcacheReq",
150    "meip"
151  )
152  for (s <- sinks){ BoringUtils.addSink(tmp, s) }
153
154  // A fake commit
155  // TODO: difftest 6 insts per cycle
156  val commit = RegNext(RegNext(RegNext(true.B)))
157  val pc = WireInit("h80000000".U)
158  val inst = WireInit("h66666666".U)
159
160  if(!p.FPGAPlatform){
161    BoringUtils.addSource(commit, "difftestCommit")
162    BoringUtils.addSource(pc, "difftestThisPC")
163    BoringUtils.addSource(inst, "difftestThisINST")
164    BoringUtils.addSource(tmp, "difftestIsMMIO")
165    BoringUtils.addSource(tmp, "difftestIsRVC")
166    BoringUtils.addSource(tmp, "difftestIntrNO")
167    BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs")
168    BoringUtils.addSource(tmp, "difftestMode")
169    BoringUtils.addSource(tmp, "difftestMstatus")
170    BoringUtils.addSource(tmp, "difftestSstatus")
171    BoringUtils.addSource(tmp, "difftestMepc")
172    BoringUtils.addSource(tmp, "difftestSepc")
173    BoringUtils.addSource(tmp, "difftestMcause")
174    BoringUtils.addSource(tmp, "difftestScause")
175  }
176
177}
178