xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision addeb2382e1afa8d88ddbf25f3de7abd2a08b35f)
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    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  io.frontend.redirect <> redirect
72  io.frontend.commits <> roq.io.commits
73
74  decode.io.in <> io.frontend.cfVec
75  brq.io.roqRedirect <> roq.io.redirect
76  brq.io.enqReqs <> decode.io.toBrq
77  decode.io.brMasks <> brq.io.brMasks
78  decode.io.brTags <> brq.io.brTags
79  decBuf.io.in <> decode.io.out
80
81  rename.io.redirect <> redirect
82  rename.io.roqCommits <> roq.io.commits
83  rename.io.in <> decBuf.io.out
84
85  dispatch1.io.redirect <> redirect
86  dispatch1.io.in <> rename.io.out
87  roq.io.brqRedirect <> brq.io.redirect
88  roq.io.dp1Req <> dispatch1.io.toRoq
89  dispatch1.io.roqIdxs <> roq.io.roqIdxs
90
91  dispatch2.io.in <> dispatch1.io.out
92  dispatch2.io.intPregRdy <> rename.io.intPregRdy
93  dispatch2.io.fpPregRdy <> rename.io.fpPregRdy
94  intRf.io.readPorts <> dispatch2.io.readIntRf
95  rename.io.intRfReadAddr <> dispatch2.io.readIntRf.map(_.addr)
96  fpRf.io.readPorts <> dispatch2.io.readFpRf
97  rename.io.fpRfReadAddr <> dispatch2.io.readFpRf.map(_.addr)
98
99
100  val exeWbReqs = exeUnits.map(_.io.out)
101  val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits)).map(_.io.out)
102  val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out)
103  val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts))
104  val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts))
105  val wbIntResults = intWbArb.io.out
106  val wbFpResults = fpWbArb.io.out
107
108  def exuOutToRfWrite(x: Valid[ExuOutput]) = {
109    val rfWrite = Wire(new RfWritePort)
110    rfWrite.wen := x.valid
111    rfWrite.addr := x.bits.uop.pdest
112    rfWrite.data := x.bits.data
113    rfWrite
114  }
115
116  intWbArb.io.in <> wbIntReqs
117  intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite)
118
119  fpWbArb.io.in <> wbFpReqs
120  fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite)
121
122  rename.io.wbIntResults <> wbIntResults
123  rename.io.wbFpResults <> wbFpResults
124
125  roq.io.exeWbResults <> exeWbReqs
126
127
128  // TODO: Remove sink and source
129  val tmp = WireInit(0.U)
130  val sinks = Array[String](
131    "DTLBFINISH",
132    "DTLBPF",
133    "DTLBENABLE",
134    "perfCntCondMdcacheLoss",
135    "perfCntCondMl2cacheLoss",
136    "perfCntCondMdcacheHit",
137    "lsuMMIO",
138    "perfCntCondMl2cacheHit",
139    "perfCntCondMl2cacheReq",
140    "mtip",
141    "perfCntCondMdcacheReq",
142    "meip"
143  )
144  for (s <- sinks){ BoringUtils.addSink(tmp, s) }
145
146  // A fake commit
147  // TODO: difftest 6 insts per cycle
148  val commit = RegNext(RegNext(RegNext(true.B)))
149  val pc = WireInit("h80000000".U)
150  val inst = WireInit("h66666666".U)
151
152  if(!p.FPGAPlatform){
153    BoringUtils.addSource(commit, "difftestCommit")
154    BoringUtils.addSource(pc, "difftestThisPC")
155    BoringUtils.addSource(inst, "difftestThisINST")
156    BoringUtils.addSource(tmp, "difftestIsMMIO")
157    BoringUtils.addSource(tmp, "difftestIsRVC")
158    BoringUtils.addSource(tmp, "difftestIntrNO")
159    BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs")
160    BoringUtils.addSource(tmp, "difftestMode")
161    BoringUtils.addSource(tmp, "difftestMstatus")
162    BoringUtils.addSource(tmp, "difftestSstatus")
163    BoringUtils.addSource(tmp, "difftestMepc")
164    BoringUtils.addSource(tmp, "difftestSepc")
165    BoringUtils.addSource(tmp, "difftestMcause")
166    BoringUtils.addSource(tmp, "difftestScause")
167  }
168
169}
170