xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision 63a5f438f61af66b62560316986298f8585433d0)
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 <> dispatch.io.enqIQCtrl(i)
59    iq.io.enqData <> dispatch.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.redirect <> redirect
101  decBuf.io.in <> decode.io.out
102
103  rename.io.redirect <> redirect
104  rename.io.roqCommits <> roq.io.commits
105  rename.io.in <> decBuf.io.out
106  rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr)
107  rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr)
108  rename.io.intPregRdy <> dispatch.io.intPregRdy
109  rename.io.fpPregRdy <> dispatch.io.fpPregRdy
110
111  dispatch.io.redirect <> redirect
112  dispatch.io.fromRename <> rename.io.out
113
114  roq.io.brqRedirect <> brq.io.redirect
115  roq.io.dp1Req <> dispatch.io.toRoq
116  dispatch.io.roqIdxs <> roq.io.roqIdxs
117
118  intRf.io.readPorts <> dispatch.io.readIntRf
119  fpRf.io.readPorts <> dispatch.io.readFpRf
120
121  val exeWbReqs = exeUnits.map(_.io.out)
122  val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits)).map(_.io.out)
123  val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out)
124  val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts))
125  val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts))
126  val wbIntResults = intWbArb.io.out
127  val wbFpResults = fpWbArb.io.out
128
129  def exuOutToRfWrite(x: Valid[ExuOutput]) = {
130    val rfWrite = Wire(new RfWritePort)
131    rfWrite.wen := x.valid
132    rfWrite.addr := x.bits.uop.pdest
133    rfWrite.data := x.bits.data
134    rfWrite
135  }
136
137  intWbArb.io.in <> wbIntReqs
138  intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite)
139
140  fpWbArb.io.in <> wbFpReqs
141  fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite)
142
143  rename.io.wbIntResults <> wbIntResults
144  rename.io.wbFpResults <> wbFpResults
145
146  roq.io.exeWbResults.zip(exeWbReqs).foreach({case (x,y) => {
147    x.bits := y.bits
148    x.valid := y.fire()
149  }})
150
151
152  // TODO: Remove sink and source
153  val tmp = WireInit(0.U)
154  val sinks = Array[String](
155    "DTLBFINISH",
156    "DTLBPF",
157    "DTLBENABLE",
158    "perfCntCondMdcacheLoss",
159    "perfCntCondMl2cacheLoss",
160    "perfCntCondMdcacheHit",
161    "lsuMMIO",
162    "perfCntCondMl2cacheHit",
163    "perfCntCondMl2cacheReq",
164    "mtip",
165    "perfCntCondMdcacheReq",
166    "meip"
167  )
168  for (s <- sinks){ BoringUtils.addSink(tmp, s) }
169
170  // A fake commit
171  // TODO: difftest 6 insts per cycle
172  val commit = RegNext(RegNext(RegNext(true.B)))
173  val pc = WireInit("h80000000".U)
174  val inst = WireInit("h66666666".U)
175
176  if(!p.FPGAPlatform){
177    BoringUtils.addSource(commit, "difftestCommit")
178    BoringUtils.addSource(pc, "difftestThisPC")
179    BoringUtils.addSource(inst, "difftestThisINST")
180    BoringUtils.addSource(tmp, "difftestIsMMIO")
181    BoringUtils.addSource(tmp, "difftestIsRVC")
182    BoringUtils.addSource(tmp, "difftestIntrNO")
183    BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs")
184    BoringUtils.addSource(tmp, "difftestMode")
185    BoringUtils.addSource(tmp, "difftestMstatus")
186    BoringUtils.addSource(tmp, "difftestSstatus")
187    BoringUtils.addSource(tmp, "difftestMepc")
188    BoringUtils.addSource(tmp, "difftestSepc")
189    BoringUtils.addSource(tmp, "difftestMcause")
190    BoringUtils.addSource(tmp, "difftestScause")
191  }
192
193}
194