xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision e402d94e38ce2810477f16c5340deb59c5756c9e)
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  // A fake commit
157  // TODO: difftest 6 insts per cycle
158  val commit = RegNext(RegNext(RegNext(true.B)))
159  val pc = WireInit("h80000000".U)
160  val inst = WireInit("h66666666".U)
161
162  if(!p.FPGAPlatform){
163    BoringUtils.addSource(commit, "difftestCommit")
164    BoringUtils.addSource(pc, "difftestThisPC")
165    BoringUtils.addSource(inst, "difftestThisINST")
166    BoringUtils.addSource(tmp, "difftestIsMMIO")
167    BoringUtils.addSource(tmp, "difftestIsRVC")
168    BoringUtils.addSource(tmp, "difftestIntrNO")
169    BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs")
170    BoringUtils.addSource(tmp, "difftestMode")
171    BoringUtils.addSource(tmp, "difftestMstatus")
172    BoringUtils.addSource(tmp, "difftestSstatus")
173    BoringUtils.addSource(tmp, "difftestMepc")
174    BoringUtils.addSource(tmp, "difftestSepc")
175    BoringUtils.addSource(tmp, "difftestMcause")
176    BoringUtils.addSource(tmp, "difftestScause")
177  }
178
179}
180