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