xref: /XiangShan/src/main/scala/xiangshan/backend/Backend.scala (revision cc4cad5ead43601b70faefecad646ef692187e45)
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
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  intRf.io.readPorts <> dispatch2.io.readIntRf
95  fpRf.io.readPorts <> dispatch2.io.readFpRf
96
97
98  val exeWbReqs = exeUnits.map(_.io.out)
99  val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits)).map(_.io.out)
100  val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out)
101  val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts))
102  val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts))
103
104  intWbArb.io.in <> wbIntReqs
105  intRf.io.writePorts <> intWbArb.io.out
106
107  fpWbArb.io.in <> wbFpReqs
108  fpRf.io.writePorts <> fpWbArb.io.out
109
110  roq.io.exeWbResults <> exeWbReqs
111
112
113  // TODO: Remove sink and source
114  val tmp = WireInit(0.U)
115  val sinks = Array[String](
116    "DTLBFINISH",
117    "DTLBPF",
118    "DTLBENABLE",
119    "perfCntCondMdcacheLoss",
120    "perfCntCondMl2cacheLoss",
121    "perfCntCondMdcacheHit",
122    "lsuMMIO",
123    "perfCntCondMl2cacheHit",
124    "perfCntCondMl2cacheReq",
125    "mtip",
126    "perfCntCondMdcacheReq",
127    "meip"
128  )
129  for (s <- sinks){ BoringUtils.addSink(tmp, s) }
130
131  // A fake commit
132  // TODO: difftest 6 insts per cycle
133  val commit = RegNext(RegNext(RegNext(true.B)))
134  val pc = WireInit("h80000000".U)
135  val inst = WireInit("h66666666".U)
136
137  if(!p.FPGAPlatform){
138    BoringUtils.addSource(commit, "difftestCommit")
139    BoringUtils.addSource(pc, "difftestThisPC")
140    BoringUtils.addSource(inst, "difftestThisINST")
141    BoringUtils.addSource(tmp, "difftestIsMMIO")
142    BoringUtils.addSource(tmp, "difftestIsRVC")
143    BoringUtils.addSource(tmp, "difftestIntrNO")
144    BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs")
145    BoringUtils.addSource(tmp, "difftestMode")
146    BoringUtils.addSource(tmp, "difftestMstatus")
147    BoringUtils.addSource(tmp, "difftestSstatus")
148    BoringUtils.addSource(tmp, "difftestMepc")
149    BoringUtils.addSource(tmp, "difftestSepc")
150    BoringUtils.addSource(tmp, "difftestMcause")
151    BoringUtils.addSource(tmp, "difftestScause")
152  }
153
154}
155