xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision 735ba814f875fb694b4c09915d563e442196eac1)
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.{Dispatch1, Dispatch2}
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 dispatch1 = Module(new Dispatch1)
38  val roq = Module(new Roq)
39  val dispatch2 = Module(new Dispatch2)
40  val intRf = Module(new Regfile(
41    numReadPorts = NRReadPorts,
42    numWirtePorts = NRWritePorts,
43    hasZero = true
44  ))
45  val fpRf = Module(new Regfile(
46    numReadPorts = NRReadPorts,
47    numWirtePorts = NRWritePorts,
48    hasZero = false
49  ))
50  val redirect = Mux(roq.io.redirect.valid, roq.io.redirect, brq.io.redirect)
51  val issueQueues = exeUnits.zipWithIndex.map({ case(eu, i) =>
52    def needWakeup(x: Exu): Boolean = (eu.readIntRf && x.writeIntRf) || (eu.readFpRf && x.writeFpRf)
53    val wakeupCnt = exeUnits.count(needWakeup)
54    val bypassCnt = if(eu.fuTypeInt == FuType.alu.litValue()) exuConfig.AluCnt else 0
55    val iq = Module(new IssueQueue(eu.fuTypeInt, wakeupCnt, bypassCnt))
56    iq.io.redirect <> redirect
57    iq.io.enqCtrl <> dispatch2.io.enqIQCtrl(i)
58    iq.io.enqData <> dispatch2.io.enqIQData(i)
59    iq.io.wakeUpPorts <> exeUnits.filter(needWakeup).map(_.io.out)
60    println(s"[$i] $eu Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt")
61    eu.io.in <> iq.io.deq
62    eu.io.redirect <> redirect
63    iq
64  })
65
66  val aluQueues = issueQueues.filter(_.fuTypeInt == FuType.alu.litValue())
67  aluQueues.foreach(aluQ => {
68    aluQ.io.bypassUops <> aluQueues.map(_.io.selectedUop)
69    aluQ.io.bypassData <> aluExeUnits.map(_.io.out)
70  })
71
72  io.frontend.redirect <> redirect
73  io.frontend.commits <> roq.io.commits
74
75  decode.io.in <> io.frontend.cfVec
76  brq.io.roqRedirect <> roq.io.redirect
77  brq.io.enqReqs <> decode.io.toBrq
78  for(i <- bjUnits.indices){
79    brq.io.exuRedirect(i).bits := bjUnits(i).io.out.bits
80    brq.io.exuRedirect(i).valid := bjUnits(i).io.out.fire()
81  }
82  decode.io.brMasks <> brq.io.brMasks
83  decode.io.brTags <> brq.io.brTags
84  decBuf.io.in <> decode.io.out
85
86  rename.io.redirect <> redirect
87  rename.io.roqCommits <> roq.io.commits
88  rename.io.in <> decBuf.io.out
89
90  dispatch1.io.redirect <> redirect
91  dispatch1.io.in <> rename.io.out
92  roq.io.brqRedirect <> brq.io.redirect
93  roq.io.dp1Req <> dispatch1.io.toRoq
94  dispatch1.io.roqIdxs <> roq.io.roqIdxs
95
96  dispatch2.io.in <> dispatch1.io.out
97  dispatch2.io.intPregRdy <> rename.io.intPregRdy
98  dispatch2.io.fpPregRdy <> rename.io.fpPregRdy
99  intRf.io.readPorts <> dispatch2.io.readIntRf
100  rename.io.intRfReadAddr <> dispatch2.io.readIntRf.map(_.addr)
101  fpRf.io.readPorts <> dispatch2.io.readFpRf
102  rename.io.fpRfReadAddr <> dispatch2.io.readFpRf.map(_.addr)
103
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