xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision 72235fa40d177945754fc14719df52b5001e2a60)
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  lsuExeUnits.foreach(_.io.dmem <> io.dmem)
73
74  io.frontend.redirect <> redirect
75  io.frontend.commits <> roq.io.commits
76
77  decode.io.in <> io.frontend.cfVec
78  brq.io.roqRedirect <> roq.io.redirect
79  brq.io.enqReqs <> decode.io.toBrq
80  for(i <- bjUnits.indices){
81    brq.io.exuRedirect(i).bits := bjUnits(i).io.out.bits
82    brq.io.exuRedirect(i).valid := bjUnits(i).io.out.fire()
83  }
84  decode.io.brMasks <> brq.io.brMasks
85  decode.io.brTags <> brq.io.brTags
86  decBuf.io.in <> decode.io.out
87
88  rename.io.redirect <> redirect
89  rename.io.roqCommits <> roq.io.commits
90  rename.io.in <> decBuf.io.out
91
92  dispatch1.io.redirect <> redirect
93  dispatch1.io.in <> rename.io.out
94  roq.io.brqRedirect <> brq.io.redirect
95  roq.io.dp1Req <> dispatch1.io.toRoq
96  dispatch1.io.roqIdxs <> roq.io.roqIdxs
97
98  dispatch2.io.in <> dispatch1.io.out
99  dispatch2.io.intPregRdy <> rename.io.intPregRdy
100  dispatch2.io.fpPregRdy <> rename.io.fpPregRdy
101  intRf.io.readPorts <> dispatch2.io.readIntRf
102  rename.io.intRfReadAddr <> dispatch2.io.readIntRf.map(_.addr)
103  fpRf.io.readPorts <> dispatch2.io.readFpRf
104  rename.io.fpRfReadAddr <> dispatch2.io.readFpRf.map(_.addr)
105
106
107  val exeWbReqs = exeUnits.map(_.io.out)
108  val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits)).map(_.io.out)
109  val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out)
110  val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts))
111  val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts))
112  val wbIntResults = intWbArb.io.out
113  val wbFpResults = fpWbArb.io.out
114
115  def exuOutToRfWrite(x: Valid[ExuOutput]) = {
116    val rfWrite = Wire(new RfWritePort)
117    rfWrite.wen := x.valid
118    rfWrite.addr := x.bits.uop.pdest
119    rfWrite.data := x.bits.data
120    rfWrite
121  }
122
123  intWbArb.io.in <> wbIntReqs
124  intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite)
125
126  fpWbArb.io.in <> wbFpReqs
127  fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite)
128
129  rename.io.wbIntResults <> wbIntResults
130  rename.io.wbFpResults <> wbFpResults
131
132  roq.io.exeWbResults.zip(exeWbReqs).foreach({case (x,y) => {
133    x.bits := y.bits
134    x.valid := y.fire()
135  }})
136
137
138  // TODO: Remove sink and source
139  val tmp = WireInit(0.U)
140  val sinks = Array[String](
141    "DTLBFINISH",
142    "DTLBPF",
143    "DTLBENABLE",
144    "perfCntCondMdcacheLoss",
145    "perfCntCondMl2cacheLoss",
146    "perfCntCondMdcacheHit",
147    "lsuMMIO",
148    "perfCntCondMl2cacheHit",
149    "perfCntCondMl2cacheReq",
150    "mtip",
151    "perfCntCondMdcacheReq",
152    "meip"
153  )
154  for (s <- sinks){ BoringUtils.addSink(tmp, s) }
155
156}
157