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