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