xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision 99dd9207279bd8aa465ce9675c552cd86a5b53ea)
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 needWakeup(x: Exu): Boolean = (eu.readIntRf && x.writeIntRf) || (eu.readFpRf && x.writeFpRf)
52    val wakeupCnt = exeUnits.count(needWakeup)
53    val bypassCnt = if(eu.fuTypeInt == FuType.alu.litValue()) exuConfig.AluCnt else 0
54    val iq = Module(new IssueQueue(eu.fuTypeInt, wakeupCnt, bypassCnt))
55    iq.io.redirect <> redirect
56    iq.io.enqCtrl <> dispatch.io.enqIQCtrl(i)
57    iq.io.enqData <> dispatch.io.enqIQData(i)
58    iq.io.wakeUpPorts <> exeUnits.filter(needWakeup).map(_.io.out)
59    println(s"[$i] $eu Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt")
60    eu.io.in <> iq.io.deq
61    eu.io.redirect <> redirect
62    iq
63  })
64
65  val aluQueues = issueQueues.filter(_.fuTypeInt == FuType.alu.litValue())
66  aluQueues.foreach(aluQ => {
67    aluQ.io.bypassUops <> aluQueues.map(_.io.selectedUop)
68    aluQ.io.bypassData <> aluExeUnits.map(_.io.out)
69  })
70
71  lsuExeUnits.foreach(_.io.dmem <> io.dmem)
72
73  io.frontend.redirect <> redirect
74  io.frontend.commits <> roq.io.commits
75
76  decode.io.in <> io.frontend.cfVec
77  brq.io.roqRedirect <> roq.io.redirect
78  brq.io.enqReqs <> decode.io.toBrq
79  for(i <- bjUnits.indices){
80    brq.io.exuRedirect(i).bits := bjUnits(i).io.out.bits
81    brq.io.exuRedirect(i).valid := bjUnits(i).io.out.fire()
82  }
83  decode.io.brMasks <> brq.io.brMasks
84  decode.io.brTags <> brq.io.brTags
85  decBuf.io.redirect <> redirect
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  rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr)
92  rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr)
93  rename.io.intPregRdy <> dispatch.io.intPregRdy
94  rename.io.fpPregRdy <> dispatch.io.fpPregRdy
95
96  dispatch.io.redirect <> redirect
97  dispatch.io.fromRename <> rename.io.out
98
99  roq.io.brqRedirect <> brq.io.redirect
100  roq.io.dp1Req <> dispatch.io.toRoq
101  dispatch.io.roqIdxs <> roq.io.roqIdxs
102
103  intRf.io.readPorts <> dispatch.io.readIntRf
104  fpRf.io.readPorts <> dispatch.io.readFpRf
105
106  val exeWbReqs = exeUnits.map(_.io.out)
107  val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits)).map(_.io.out)
108  val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out)
109  val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts))
110  val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts))
111  val wbIntResults = intWbArb.io.out
112  val wbFpResults = fpWbArb.io.out
113
114  def exuOutToRfWrite(x: Valid[ExuOutput]) = {
115    val rfWrite = Wire(new RfWritePort)
116    rfWrite.wen := x.valid
117    rfWrite.addr := x.bits.uop.pdest
118    rfWrite.data := x.bits.data
119    rfWrite
120  }
121
122  intWbArb.io.in <> wbIntReqs
123  intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite)
124
125  fpWbArb.io.in <> wbFpReqs
126  fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite)
127
128  rename.io.wbIntResults <> wbIntResults
129  rename.io.wbFpResults <> wbFpResults
130
131  roq.io.exeWbResults.zip(exeWbReqs).foreach({case (x,y) => {
132    x.bits := y.bits
133    x.valid := y.fire()
134  }})
135
136
137  // TODO: Remove sink and source
138  val tmp = WireInit(0.U)
139  val sinks = Array[String](
140    "DTLBFINISH",
141    "DTLBPF",
142    "DTLBENABLE",
143    "perfCntCondMdcacheLoss",
144    "perfCntCondMl2cacheLoss",
145    "perfCntCondMdcacheHit",
146    "lsuMMIO",
147    "perfCntCondMl2cacheHit",
148    "perfCntCondMl2cacheReq",
149    "mtip",
150    "perfCntCondMdcacheReq",
151    "meip"
152  )
153  for (s <- sinks){ BoringUtils.addSink(tmp, s) }
154
155  // A fake commit
156  // TODO: difftest 6 insts per cycle
157  val commit = RegNext(RegNext(RegNext(true.B)))
158  val pc = WireInit("h80000000".U)
159  val inst = WireInit("h66666666".U)
160
161  if(!p.FPGAPlatform){
162    BoringUtils.addSource(commit, "difftestCommit")
163    BoringUtils.addSource(pc, "difftestThisPC")
164    BoringUtils.addSource(inst, "difftestThisINST")
165    BoringUtils.addSource(tmp, "difftestIsMMIO")
166    BoringUtils.addSource(tmp, "difftestIsRVC")
167    BoringUtils.addSource(tmp, "difftestIntrNO")
168    BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs")
169    BoringUtils.addSource(tmp, "difftestMode")
170    BoringUtils.addSource(tmp, "difftestMstatus")
171    BoringUtils.addSource(tmp, "difftestSstatus")
172    BoringUtils.addSource(tmp, "difftestMepc")
173    BoringUtils.addSource(tmp, "difftestSepc")
174    BoringUtils.addSource(tmp, "difftestMcause")
175    BoringUtils.addSource(tmp, "difftestScause")
176  }
177
178}
179