xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision 88b0b551c0c271fb814605fbf735202e08dbd9eb)
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 <> exeWbReqs
131
132
133  // TODO: Remove sink and source
134  val tmp = WireInit(0.U)
135  val sinks = Array[String](
136    "DTLBFINISH",
137    "DTLBPF",
138    "DTLBENABLE",
139    "perfCntCondMdcacheLoss",
140    "perfCntCondMl2cacheLoss",
141    "perfCntCondMdcacheHit",
142    "lsuMMIO",
143    "perfCntCondMl2cacheHit",
144    "perfCntCondMl2cacheReq",
145    "mtip",
146    "perfCntCondMdcacheReq",
147    "meip"
148  )
149  for (s <- sinks){ BoringUtils.addSink(tmp, s) }
150
151  // A fake commit
152  // TODO: difftest 6 insts per cycle
153  val commit = RegNext(RegNext(RegNext(true.B)))
154  val pc = WireInit("h80000000".U)
155  val inst = WireInit("h66666666".U)
156
157  if(!p.FPGAPlatform){
158    BoringUtils.addSource(commit, "difftestCommit")
159    BoringUtils.addSource(pc, "difftestThisPC")
160    BoringUtils.addSource(inst, "difftestThisINST")
161    BoringUtils.addSource(tmp, "difftestIsMMIO")
162    BoringUtils.addSource(tmp, "difftestIsRVC")
163    BoringUtils.addSource(tmp, "difftestIntrNO")
164    BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs")
165    BoringUtils.addSource(tmp, "difftestMode")
166    BoringUtils.addSource(tmp, "difftestMstatus")
167    BoringUtils.addSource(tmp, "difftestSstatus")
168    BoringUtils.addSource(tmp, "difftestMepc")
169    BoringUtils.addSource(tmp, "difftestSepc")
170    BoringUtils.addSource(tmp, "difftestMcause")
171    BoringUtils.addSource(tmp, "difftestScause")
172  }
173
174}
175