xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision 8557b6eccaf5d76a0b292ca79d5b79641dd8de83)
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
50  // backend redirect, flush pipeline
51  val redirect = Mux(roq.io.redirect.valid, roq.io.redirect, brq.io.redirect)
52
53  val redirectInfo = Wire(new RedirectInfo)
54  // exception or misprediction
55  redirectInfo.valid := roq.io.redirect.valid || brq.io.out.valid
56  redirectInfo.misPred := !roq.io.redirect.valid && brq.io.redirect.valid
57  redirectInfo.redirect := redirect.bits
58
59  val issueQueues = exeUnits.zipWithIndex.map({ case(eu, i) =>
60    def needBypass(x: Exu): Boolean = eu.enableBypass
61    val bypassCnt = exeUnits.count(needBypass)//if(eu.fuTypeInt == FuType.alu.litValue()) exuConfig.AluCnt else 0
62    def needWakeup(x: Exu): Boolean = (eu.readIntRf && x.writeIntRf) || (eu.readFpRf && x.writeFpRf)
63    val wakeupCnt = exeUnits.count(needWakeup)
64    assert(!(needBypass(eu) && !needWakeup(eu))) // needBypass but dont needWakeup is not allowed
65    val iq = Module(new IssueQueue(eu.fuTypeInt, wakeupCnt, bypassCnt, eu.fixedDelay, fifo = eu.fuTypeInt == FuType.ldu.litValue()))
66    iq.io.redirect <> redirect
67    iq.io.numExist <> dispatch.io.numExist(i)
68    iq.io.enqCtrl <> dispatch.io.enqIQCtrl(i)
69    iq.io.enqData <> dispatch.io.enqIQData(i)
70    val wuUnitsOut = exeUnits.filter(e => needWakeup(e)).map(_.io.out)
71    for(i <- iq.io.wakeUpPorts.indices) {
72      iq.io.wakeUpPorts(i).bits <> wuUnitsOut(i).bits
73      iq.io.wakeUpPorts(i).valid := wuUnitsOut(i).valid
74    }
75    println(s"[$i] $eu Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt")
76    eu.io.in <> iq.io.deq
77    eu.io.redirect <> redirect
78    iq
79  })
80
81  val bypassQueues = issueQueues.filter(_.bypassCnt > 0)
82  val bypassUnits = exeUnits.filter(_.enableBypass)
83  bypassQueues.foreach(iq => {
84    for(i <- iq.io.bypassUops.indices) {
85      iq.io.bypassData(i).bits := bypassUnits(i).io.out.bits
86      iq.io.bypassData(i).valid := bypassUnits(i).io.out.valid
87    }
88    iq.io.bypassUops <> bypassQueues.map(_.io.selectedUop)
89  })
90  // val aluQueues = issueQueues.filter(_.fuTypeInt == FuType.alu.litValue())
91  // aluQueues.foreach(aluQ => {
92  //   aluQ.io.bypassUops <> aluQueues.map(_.io.selectedUop)
93  //   aluQ.io.bypassData <> aluExeUnits.map(_.io.out)
94  // })
95
96  lsuExeUnits.foreach(_.io.dmem <> io.dmem)
97  lsuExeUnits.foreach(_.io.scommit <> roq.io.scommit)
98
99  io.frontend.redirectInfo <> redirectInfo
100  io.frontend.commits <> roq.io.commits
101
102  decode.io.in <> io.frontend.cfVec
103  brq.io.roqRedirect <> roq.io.redirect
104  brq.io.enqReqs <> decode.io.toBrq
105  for((x, y) <- brq.io.exuRedirect.zip(exeUnits.filter(_.hasRedirect))){
106    x.bits := y.io.out.bits
107    x.valid := y.io.out.fire() && y.io.out.bits.redirectValid
108  }
109  decode.io.brTags <> brq.io.brTags
110  decBuf.io.redirect <> redirect
111  decBuf.io.in <> decode.io.out
112
113  rename.io.redirect <> redirect
114  rename.io.roqCommits <> roq.io.commits
115  rename.io.in <> decBuf.io.out
116  rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr)
117  rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr)
118  rename.io.intPregRdy <> dispatch.io.intPregRdy
119  rename.io.fpPregRdy <> dispatch.io.fpPregRdy
120
121  dispatch.io.redirect <> redirect
122  dispatch.io.fromRename <> rename.io.out
123
124  roq.io.brqRedirect <> brq.io.redirect
125  roq.io.dp1Req <> dispatch.io.toRoq
126  dispatch.io.roqIdxs <> roq.io.roqIdxs
127
128  intRf.io.readPorts <> dispatch.io.readIntRf
129  fpRf.io.readPorts <> dispatch.io.readFpRf
130
131  val exeWbReqs = exeUnits.map(_.io.out)
132
133  val wbIntIdx = exeUnits.zipWithIndex.filter(_._1.writeIntRf).map(_._2)
134  val wbFpIdx = exeUnits.zipWithIndex.filter(_._1.writeFpRf).map(_._2)
135
136  val wbu = Module(new Wbu(wbIntIdx, wbFpIdx))
137  wbu.io.in <> exeWbReqs
138
139  val wbIntResults = wbu.io.toIntRf
140  val wbFpResults = wbu.io.toFpRf
141
142  def exuOutToRfWrite(x: Valid[ExuOutput]): RfWritePort = {
143    val rfWrite = Wire(new RfWritePort)
144    rfWrite.wen := x.valid
145    rfWrite.addr := x.bits.uop.pdest
146    rfWrite.data := x.bits.data
147    rfWrite
148  }
149
150  intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite)
151  fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite)
152
153  rename.io.wbIntResults <> wbIntResults
154  rename.io.wbFpResults <> wbFpResults
155
156  roq.io.exeWbResults.take(exeWbReqs.length).zip(wbu.io.toRoq).foreach(x => x._1 := x._2)
157  roq.io.exeWbResults.last := brq.io.out
158
159
160  // TODO: Remove sink and source
161  val tmp = WireInit(0.U)
162  val sinks = Array[String](
163    "DTLBFINISH",
164    "DTLBPF",
165    "DTLBENABLE",
166    "perfCntCondMdcacheLoss",
167    "perfCntCondMl2cacheLoss",
168    "perfCntCondMdcacheHit",
169    "lsuMMIO",
170    "perfCntCondMl2cacheHit",
171    "perfCntCondMl2cacheReq",
172    "mtip",
173    "perfCntCondMdcacheReq",
174    "meip"
175  )
176  for (s <- sinks){ BoringUtils.addSink(tmp, s) }
177
178  val debugIntReg, debugFpReg = WireInit(VecInit(Seq.fill(32)(0.U(XLEN.W))))
179  BoringUtils.addSink(debugIntReg, "DEBUG_INT_ARCH_REG")
180  BoringUtils.addSink(debugFpReg, "DEBUG_FP_ARCH_REG")
181  val debugArchReg = WireInit(VecInit(debugIntReg ++ debugFpReg))
182  if(!p.FPGAPlatform){
183    BoringUtils.addSource(debugArchReg, "difftestRegs")
184  }
185
186}
187