xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision ad55d1948259e3d0033d37bc72e751e33b771a77)
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    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  })
69
70  io.frontend.redirect <> redirect
71  io.frontend.commits <> roq.io.commits
72
73  decode.io.in <> io.frontend.cfVec
74  brq.io.roqRedirect <> roq.io.redirect
75  brq.io.enqReqs <> decode.io.toBrq
76  decode.io.brMasks <> brq.io.brMasks
77  decode.io.brTags <> brq.io.brTags
78  decBuf.io.in <> decode.io.out
79
80  rename.io.redirect <> redirect
81  rename.io.roqCommits <> roq.io.commits
82  rename.io.in <> decBuf.io.out
83
84  dispatch1.io.redirect <> redirect
85  dispatch1.io.in <> rename.io.out
86  roq.io.brqRedirect <> brq.io.redirect
87  roq.io.dp1Req <> dispatch1.io.toRoq
88  dispatch1.io.roqIdxs <> roq.io.roqIdxs
89
90  dispatch2.io.in <> dispatch1.io.out
91  dispatch2.io.intPregRdy <> rename.io.intPregRdy
92  dispatch2.io.fpPregRdy <> rename.io.fpPregRdy
93  intRf.io.readPorts <> dispatch2.io.readIntRf
94  rename.io.intRfReadAddr <> dispatch2.io.readIntRf.map(_.addr)
95  fpRf.io.readPorts <> dispatch2.io.readFpRf
96  rename.io.fpRfReadAddr <> dispatch2.io.readFpRf.map(_.addr)
97
98
99  val exeWbReqs = exeUnits.map(_.io.out)
100  val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits)).map(_.io.out)
101  val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out)
102  val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts))
103  val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts))
104  val wbIntResults = intWbArb.io.out
105  val wbFpResults = fpWbArb.io.out
106
107  def exuOutToRfWrite(x: Valid[ExuOutput]) = {
108    val rfWrite = Wire(new RfWritePort)
109    rfWrite.wen := x.valid
110    rfWrite.addr := x.bits.uop.pdest
111    rfWrite.data := x.bits.data
112    rfWrite
113  }
114
115  intWbArb.io.in <> wbIntReqs
116  intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite)
117
118  fpWbArb.io.in <> wbFpReqs
119  fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite)
120
121  rename.io.wbIntResults <> wbIntResults
122  rename.io.wbFpResults <> wbFpResults
123
124  roq.io.exeWbResults <> exeWbReqs
125
126
127  // TODO: Remove sink and source
128  val tmp = WireInit(0.U)
129  val sinks = Array[String](
130    "DTLBFINISH",
131    "DTLBPF",
132    "DTLBENABLE",
133    "perfCntCondMdcacheLoss",
134    "perfCntCondMl2cacheLoss",
135    "perfCntCondMdcacheHit",
136    "lsuMMIO",
137    "perfCntCondMl2cacheHit",
138    "perfCntCondMl2cacheReq",
139    "mtip",
140    "perfCntCondMdcacheReq",
141    "meip"
142  )
143  for (s <- sinks){ BoringUtils.addSink(tmp, s) }
144
145  // A fake commit
146  // TODO: difftest 6 insts per cycle
147  val commit = RegNext(RegNext(RegNext(true.B)))
148  val pc = WireInit("h80000000".U)
149  val inst = WireInit("h66666666".U)
150
151  if(!p.FPGAPlatform){
152    BoringUtils.addSource(commit, "difftestCommit")
153    BoringUtils.addSource(pc, "difftestThisPC")
154    BoringUtils.addSource(inst, "difftestThisINST")
155    BoringUtils.addSource(tmp, "difftestIsMMIO")
156    BoringUtils.addSource(tmp, "difftestIsRVC")
157    BoringUtils.addSource(tmp, "difftestIntrNO")
158    BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs")
159    BoringUtils.addSource(tmp, "difftestMode")
160    BoringUtils.addSource(tmp, "difftestMstatus")
161    BoringUtils.addSource(tmp, "difftestSstatus")
162    BoringUtils.addSource(tmp, "difftestMepc")
163    BoringUtils.addSource(tmp, "difftestSepc")
164    BoringUtils.addSource(tmp, "difftestMcause")
165    BoringUtils.addSource(tmp, "difftestScause")
166  }
167
168}
169