xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision 986a0bb07b06493d0eb7cfb0155c29700d263cdb)
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 needBypass(x: Exu): Boolean = (eu.enableBypass)
53    val bypassCnt = exeUnits.count(needBypass)//if(eu.fuTypeInt == FuType.alu.litValue()) exuConfig.AluCnt else 0
54    def needWakeup(x: Exu): Boolean = (eu.readIntRf && x.writeIntRf) || (eu.readFpRf && x.writeFpRf)
55    val wakeupCnt = exeUnits.count(needWakeup) - (if(eu.enableBypass) bypassCnt else 0)
56    assert(!(needBypass(eu) && !needWakeup(eu))) // needBypass but dont needWakeup is not allowed
57    val iq = Module(new IssueQueue(eu.fuTypeInt, wakeupCnt, bypassCnt, eu.fixedDelay))
58    iq.io.redirect <> redirect
59    iq.io.enqCtrl <> dispatch2.io.enqIQCtrl(i)
60    iq.io.enqData <> dispatch2.io.enqIQData(i)
61    iq.io.wakeUpPorts <> exeUnits.filter(e => needWakeup(e) && !needBypass(e)).map(_.io.out)
62    println(s"[$i] $eu Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt")
63    eu.io.in <> iq.io.deq
64    iq
65  })
66
67  val bypassQueues = issueQueues.filter(_.bypassCnt > 0)
68  val bypassUnits = exeUnits.filter(_.enableBypass)
69  bypassQueues.foreach(iq => {
70    iq.io.bypassUops <> bypassQueues.map(_.io.selectedUop)
71    iq.io.bypassData <> bypassUnits.map(_.io.out)
72  })
73  // val aluQueues = issueQueues.filter(_.fuTypeInt == FuType.alu.litValue())
74  // aluQueues.foreach(aluQ => {
75  //   aluQ.io.bypassUops <> aluQueues.map(_.io.selectedUop)
76  //   aluQ.io.bypassData <> aluExeUnits.map(_.io.out)
77  // })
78
79  io.frontend.redirect <> redirect
80  io.frontend.commits <> roq.io.commits
81
82  decode.io.in <> io.frontend.cfVec
83  brq.io.roqRedirect <> roq.io.redirect
84  brq.io.enqReqs <> decode.io.toBrq
85  decode.io.brMasks <> brq.io.brMasks
86  decode.io.brTags <> brq.io.brTags
87  decBuf.io.in <> decode.io.out
88
89  rename.io.redirect <> redirect
90  rename.io.roqCommits <> roq.io.commits
91  rename.io.in <> decBuf.io.out
92
93  dispatch1.io.redirect <> redirect
94  dispatch1.io.in <> rename.io.out
95  roq.io.brqRedirect <> brq.io.redirect
96  roq.io.dp1Req <> dispatch1.io.toRoq
97  dispatch1.io.roqIdxs <> roq.io.roqIdxs
98
99  dispatch2.io.in <> dispatch1.io.out
100  dispatch2.io.intPregRdy <> rename.io.intPregRdy
101  dispatch2.io.fpPregRdy <> rename.io.fpPregRdy
102  intRf.io.readPorts <> dispatch2.io.readIntRf
103  rename.io.intRfReadAddr <> dispatch2.io.readIntRf.map(_.addr)
104  fpRf.io.readPorts <> dispatch2.io.readFpRf
105  rename.io.fpRfReadAddr <> dispatch2.io.readFpRf.map(_.addr)
106
107
108  val exeWbReqs = exeUnits.map(_.io.out)
109  val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits)).map(_.io.out)
110  val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out)
111  val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts))
112  val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts))
113  val wbIntResults = intWbArb.io.out
114  val wbFpResults = fpWbArb.io.out
115
116  def exuOutToRfWrite(x: Valid[ExuOutput]) = {
117    val rfWrite = Wire(new RfWritePort)
118    rfWrite.wen := x.valid
119    rfWrite.addr := x.bits.uop.pdest
120    rfWrite.data := x.bits.data
121    rfWrite
122  }
123
124  intWbArb.io.in <> wbIntReqs
125  intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite)
126
127  fpWbArb.io.in <> wbFpReqs
128  fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite)
129
130  rename.io.wbIntResults <> wbIntResults
131  rename.io.wbFpResults <> wbFpResults
132
133  roq.io.exeWbResults <> exeWbReqs
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