xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision f56615ce4a789edbfb242e4a48da81473a549be0)
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 ++ lsuExeUnits)).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}
171