xref: /XiangShan/src/main/scala/xiangshan/backend/rename/BusyTable.scala (revision ef2bf60e38eb96a59854268d49db8e9cde3752e7)
1c6d43980SLemover/***************************************************************************************
2c6d43980SLemover* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3f320e0f0SYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory
4c6d43980SLemover*
5c6d43980SLemover* XiangShan is licensed under Mulan PSL v2.
6c6d43980SLemover* You can use this software according to the terms and conditions of the Mulan PSL v2.
7c6d43980SLemover* You may obtain a copy of Mulan PSL v2 at:
8c6d43980SLemover*          http://license.coscl.org.cn/MulanPSL2
9c6d43980SLemover*
10c6d43980SLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11c6d43980SLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12c6d43980SLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13c6d43980SLemover*
14c6d43980SLemover* See the Mulan PSL v2 for more details.
15c6d43980SLemover***************************************************************************************/
16c6d43980SLemover
17b034d3b9SLinJiaweipackage xiangshan.backend.rename
18b034d3b9SLinJiawei
198891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters
20b034d3b9SLinJiaweiimport chisel3._
21b034d3b9SLinJiaweiimport chisel3.util._
22b034d3b9SLinJiaweiimport xiangshan._
23d479a3a8SYinan Xuimport utils._
243c02ee8fSwakafaimport utility._
25bc7d6943SzhanglyGitimport xiangshan.backend.Bundles._
264eebf274Ssinsanctionimport xiangshan.backend.datapath.WbConfig._
27bc7d6943SzhanglyGitimport xiangshan.backend.issue.SchdBlockParams
28bc7d6943SzhanglyGitimport xiangshan.backend.datapath.{DataSource}
29bc7d6943SzhanglyGit
302225d46eSJiawei Linclass BusyTableReadIO(implicit p: Parameters) extends XSBundle {
318af95560SYinan Xu  val req = Input(UInt(PhyRegIdxWidth.W))
328af95560SYinan Xu  val resp = Output(Bool())
33ec49b127Ssinsanction  val loadDependency = Vec(LoadPipelineWidth, Output(UInt(LoadDependencyWidth.W)))
348af95560SYinan Xu}
358af95560SYinan Xu
36bc7d6943SzhanglyGitclass BusyTable(numReadPorts: Int, numWritePorts: Int, numPhyPregs: Int, pregWB: PregWB)(implicit p: Parameters, params: SchdBlockParams) extends XSModule with HasPerfEvents {
37b034d3b9SLinJiawei  val io = IO(new Bundle() {
38b034d3b9SLinJiawei    // set preg state to busy
39b034d3b9SLinJiawei    val allocPregs = Vec(RenameWidth, Flipped(ValidIO(UInt(PhyRegIdxWidth.W))))
409aca92b9SYinan Xu    // set preg state to ready (write back regfile + rob walk)
416624015fSLinJiawei    val wbPregs = Vec(numWritePorts, Flipped(ValidIO(UInt(PhyRegIdxWidth.W))))
42bc7d6943SzhanglyGit    // fast wakeup
43bc7d6943SzhanglyGit    val wakeUp: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpInValidBundle)
44bc7d6943SzhanglyGit    // cancelFromDatapath
45be9ff987Ssinsanction    val og0Cancel = Input(ExuVec())
4613551487SzhanglyGit    // cancelFromMem
4713551487SzhanglyGit    val ldCancel = Vec(backendParams.LdExuCnt, Flipped(new LoadCancelIO))
48b034d3b9SLinJiawei    // read preg state
498af95560SYinan Xu    val read = Vec(numReadPorts, new BusyTableReadIO)
50b034d3b9SLinJiawei  })
51b034d3b9SLinJiawei
52e600b1ddSxiaofeibao-xjtu  val allExuParams = params.backendParam.allExuParams
53e600b1ddSxiaofeibao-xjtu  val intBusyTableNeedLoadCancel = allExuParams.map(x =>
54e600b1ddSxiaofeibao-xjtu    x.needLoadDependency && x.writeIntRf && x.iqWakeUpSourcePairs.map(y => y.sink.getExuParam(allExuParams).readIntRf).foldLeft(false)(_ || _)
55e600b1ddSxiaofeibao-xjtu  ).reduce(_ || _)
56e600b1ddSxiaofeibao-xjtu  val fpBusyTableNeedLoadCancel = allExuParams.map(x =>
57e600b1ddSxiaofeibao-xjtu    x.needLoadDependency && x.writeFpRf && x.iqWakeUpSourcePairs.map(y => y.sink.getExuParam(allExuParams).readFpRf).foldLeft(false)(_ || _)
58e600b1ddSxiaofeibao-xjtu  ).reduce(_ || _)
59e600b1ddSxiaofeibao-xjtu  val vfBusyTableNeedLoadCancel = allExuParams.map(x =>
60e600b1ddSxiaofeibao-xjtu    x.needLoadDependency && x.writeVfRf && x.iqWakeUpSourcePairs.map(y => y.sink.getExuParam(allExuParams).readVecRf).foldLeft(false)(_ || _)
61e600b1ddSxiaofeibao-xjtu  ).reduce(_ || _)
62e600b1ddSxiaofeibao-xjtu  val v0BusyTableNeedLoadCancel = allExuParams.map(x =>
63e600b1ddSxiaofeibao-xjtu    x.needLoadDependency && x.writeV0Rf && x.iqWakeUpSourcePairs.map(y => y.sink.getExuParam(allExuParams).readVecRf).foldLeft(false)(_ || _)
64e600b1ddSxiaofeibao-xjtu  ).reduce(_ || _)
65e600b1ddSxiaofeibao-xjtu  val vlBusyTableNeedLoadCancel = allExuParams.map(x =>
66e600b1ddSxiaofeibao-xjtu    x.needLoadDependency && x.writeVlRf && x.iqWakeUpSourcePairs.map(y => y.sink.getExuParam(allExuParams).readVlRf).foldLeft(false)(_ || _)
67e600b1ddSxiaofeibao-xjtu  ).reduce(_ || _)
68e600b1ddSxiaofeibao-xjtu  val needLoadCancel = pregWB match {
69e600b1ddSxiaofeibao-xjtu    case IntWB(_, _) => intBusyTableNeedLoadCancel
70e600b1ddSxiaofeibao-xjtu    case FpWB(_, _) => fpBusyTableNeedLoadCancel
71e600b1ddSxiaofeibao-xjtu    case VfWB(_, _) => vfBusyTableNeedLoadCancel
72e600b1ddSxiaofeibao-xjtu    case V0WB(_, _) => v0BusyTableNeedLoadCancel
73e600b1ddSxiaofeibao-xjtu    case VlWB(_, _) => vlBusyTableNeedLoadCancel
74e600b1ddSxiaofeibao-xjtu    case _ => throw new IllegalArgumentException(s"WbConfig ${pregWB} is not permitted")
75e600b1ddSxiaofeibao-xjtu  }
76e600b1ddSxiaofeibao-xjtu  if (!needLoadCancel) println(s"[BusyTable]: WbConfig ${pregWB} busyTable don't need loadCancel")
77e600b1ddSxiaofeibao-xjtu  val loadCancel = if (needLoadCancel) io.ldCancel else 0.U.asTypeOf(io.ldCancel)
78*ef2bf60eSxiaofeibao-xjtu  val wakeUpIn = pregWB match {
79*ef2bf60eSxiaofeibao-xjtu    case IntWB(_, _) => io.wakeUp.filter(_.bits.params.writeIntRf)
80*ef2bf60eSxiaofeibao-xjtu    case FpWB(_, _) => io.wakeUp.filter(_.bits.params.writeFpRf)
81*ef2bf60eSxiaofeibao-xjtu    case VfWB(_, _) => io.wakeUp.filter(_.bits.params.writeVfRf)
82*ef2bf60eSxiaofeibao-xjtu    case V0WB(_, _) => io.wakeUp.filter(_.bits.params.writeV0Rf)
83*ef2bf60eSxiaofeibao-xjtu    case VlWB(_, _) => io.wakeUp.filter(_.bits.params.writeVlRf)
84*ef2bf60eSxiaofeibao-xjtu    case _ => throw new IllegalArgumentException(s"WbConfig ${pregWB} is not permitted")
85*ef2bf60eSxiaofeibao-xjtu  }
86ec49b127Ssinsanction  val loadDependency = RegInit(0.U.asTypeOf(Vec(numPhyPregs, Vec(LoadPipelineWidth, UInt(LoadDependencyWidth.W)))))
87*ef2bf60eSxiaofeibao-xjtu  val shiftLoadDependency = Wire(Vec(wakeUpIn.size, Vec(LoadPipelineWidth, UInt(LoadDependencyWidth.W))))
880030d978SzhanglyGit  val tableUpdate = Wire(Vec(numPhyPregs, Bool()))
89*ef2bf60eSxiaofeibao-xjtu  val wakeupOHVec = Wire(Vec(numPhyPregs, UInt(wakeUpIn.size.W)))
90767bd21fSLinJiawei
9160deaca2SLinJiawei  def reqVecToMask(rVec: Vec[Valid[UInt]]): UInt = {
9260deaca2SLinJiawei    ParallelOR(rVec.map(v => Mux(v.valid, UIntToOH(v.bits), 0.U)))
9360deaca2SLinJiawei  }
9460deaca2SLinJiawei
95*ef2bf60eSxiaofeibao-xjtu  shiftLoadDependency.zip(wakeUpIn).map{ case (deps, wakeup) =>
96*ef2bf60eSxiaofeibao-xjtu    if (wakeup.bits.params.hasLoadExu) {
97*ef2bf60eSxiaofeibao-xjtu      deps.zipWithIndex.map{ case (dep, i) =>
98*ef2bf60eSxiaofeibao-xjtu        if (backendParams.getLdExuIdx(wakeup.bits.params) == i) dep := 1.U
99*ef2bf60eSxiaofeibao-xjtu        else dep := 0.U
100*ef2bf60eSxiaofeibao-xjtu      }
101*ef2bf60eSxiaofeibao-xjtu    }
102*ef2bf60eSxiaofeibao-xjtu    else {
103*ef2bf60eSxiaofeibao-xjtu      deps.zip(wakeup.bits.loadDependency).map{ case (sink, source) =>
104*ef2bf60eSxiaofeibao-xjtu        sink := source << 1
105*ef2bf60eSxiaofeibao-xjtu      }
10613551487SzhanglyGit    }
10713551487SzhanglyGit  }
10813551487SzhanglyGit
10913551487SzhanglyGit  wakeupOHVec.zipWithIndex.foreach{ case (wakeupOH, idx) =>
11013551487SzhanglyGit    val tmp = pregWB match {
111*ef2bf60eSxiaofeibao-xjtu      case IntWB(_, _) => wakeUpIn.map(x => x.valid && x.bits.rfWen  && UIntToOH(x.bits.pdest)(idx) && !LoadShouldCancel(Some(x.bits.loadDependency), loadCancel) && !(x.bits.is0Lat && io.og0Cancel(x.bits.params.exuIdx)))
112*ef2bf60eSxiaofeibao-xjtu      case FpWB(_, _)  => wakeUpIn.map(x => x.valid && x.bits.fpWen  && UIntToOH(x.bits.pdest)(idx) && !LoadShouldCancel(Some(x.bits.loadDependency), loadCancel) && !(x.bits.is0Lat && io.og0Cancel(x.bits.params.exuIdx)))
113*ef2bf60eSxiaofeibao-xjtu      case VfWB(_, _)  => wakeUpIn.map(x => x.valid && x.bits.vecWen && UIntToOH(x.bits.pdest)(idx) && !LoadShouldCancel(Some(x.bits.loadDependency), loadCancel) && !(x.bits.is0Lat && io.og0Cancel(x.bits.params.exuIdx)))
114*ef2bf60eSxiaofeibao-xjtu      case V0WB(_, _)  => wakeUpIn.map(x => x.valid && x.bits.v0Wen  && UIntToOH(x.bits.pdest)(idx) && !LoadShouldCancel(Some(x.bits.loadDependency), loadCancel) && !(x.bits.is0Lat && io.og0Cancel(x.bits.params.exuIdx)))
115*ef2bf60eSxiaofeibao-xjtu      case VlWB(_, _)  => wakeUpIn.map(x => x.valid && x.bits.vlWen  && UIntToOH(x.bits.pdest)(idx) && !LoadShouldCancel(Some(x.bits.loadDependency), loadCancel) && !(x.bits.is0Lat && io.og0Cancel(x.bits.params.exuIdx)))
1164eebf274Ssinsanction      case _ => throw new IllegalArgumentException(s"WbConfig ${pregWB} is not permitted")
11713551487SzhanglyGit    }
118*ef2bf60eSxiaofeibao-xjtu    wakeupOH := (if (wakeUpIn.nonEmpty) VecInit(tmp.toSeq).asUInt else 0.U)
11913551487SzhanglyGit  }
12060deaca2SLinJiawei  val wbMask = reqVecToMask(io.wbPregs)
12160deaca2SLinJiawei  val allocMask = reqVecToMask(io.allocPregs)
12213551487SzhanglyGit  val wakeUpMask = VecInit(wakeupOHVec.map(_.orR).toSeq).asUInt
123e600b1ddSxiaofeibao-xjtu  val ldCancelMask = loadDependency.map(x => LoadShouldCancel(Some(x), loadCancel))
12413551487SzhanglyGit
12513551487SzhanglyGit  loadDependency.zipWithIndex.foreach{ case (ldDp, idx) =>
12637080bd8Ssinsanction    when(allocMask(idx) || wbMask(idx) || ldCancelMask(idx)) {
12713551487SzhanglyGit      ldDp := 0.U.asTypeOf(ldDp)
12813551487SzhanglyGit    }.elsewhen(wakeUpMask(idx)) {
129*ef2bf60eSxiaofeibao-xjtu      ldDp := (if (wakeUpIn.nonEmpty) Mux1H(wakeupOHVec(idx), shiftLoadDependency) else 0.U.asTypeOf(ldDp))
13041dbbdfdSsinceforYy    }.elsewhen(ldDp.map(x => x.orR).reduce(_ | _)) {
131ec49b127Ssinsanction      ldDp := VecInit(ldDp.map(x => x << 1))
13213551487SzhanglyGit    }
13313551487SzhanglyGit  }
134d479a3a8SYinan Xu
135bc7d6943SzhanglyGit  /*
136bc7d6943SzhanglyGit  we can ensure that the following conditions are mutually exclusive
1370030d978SzhanglyGit  wakeUp and cancel (same pdest) may arrive at the same cycle
138bc7d6943SzhanglyGit  for a pdest:
1390030d978SzhanglyGit    rename alloc => wakeUp / cancel => ... => wakeUp / cancel => wakeUp
140bc7d6943SzhanglyGit  or
141bc7d6943SzhanglyGit    rename alloc => wbMask  //TODO we still need wbMask because wakeUp signal is partial now
142bc7d6943SzhanglyGit  the bypass state lasts for a maximum of one cycle, cancel(=> busy) or else(=> regFile)
143bc7d6943SzhanglyGit   */
14441dbbdfdSsinceforYy  val table = VecInit((0 until numPhyPregs).zip(tableUpdate).map{ case (idx, update) =>
14537080bd8Ssinsanction    RegEnable(update, 0.U(1.W), allocMask(idx) || ldCancelMask(idx) || wakeUpMask(idx) || wbMask(idx))
14641dbbdfdSsinceforYy  }).asUInt
14741dbbdfdSsinceforYy
148bc7d6943SzhanglyGit  tableUpdate.zipWithIndex.foreach{ case (update, idx) =>
14937080bd8Ssinsanction    when(allocMask(idx) || ldCancelMask(idx)) {
15013551487SzhanglyGit      update := true.B                                    //busy
15137c998e1Sxiaofeibao-xjtu      if (idx == 0 && pregWB.isInstanceOf[IntWB]) {
15237c998e1Sxiaofeibao-xjtu          // Int RegFile 0 is always ready
15337c998e1Sxiaofeibao-xjtu          update := false.B
15437c998e1Sxiaofeibao-xjtu      }
1550030d978SzhanglyGit    }.elsewhen(wakeUpMask(idx) || wbMask(idx)) {
15613551487SzhanglyGit      update := false.B                                   //ready
157bc7d6943SzhanglyGit    }.otherwise {
158bc7d6943SzhanglyGit      update := table(idx)
159bc7d6943SzhanglyGit    }
160bc7d6943SzhanglyGit  }
161bc7d6943SzhanglyGit
162bc7d6943SzhanglyGit  io.read.foreach{ case res =>
1630030d978SzhanglyGit    res.resp := !table(res.req)
16413551487SzhanglyGit    res.loadDependency := loadDependency(res.req)
165bc7d6943SzhanglyGit  }
166bc7d6943SzhanglyGit
1670030d978SzhanglyGit  val oddTable = table.asBools.zipWithIndex.filter(_._2 % 2 == 1).map(_._1)
1680030d978SzhanglyGit  val evenTable = table.asBools.zipWithIndex.filter(_._2 % 2 == 0).map(_._1)
169bc7d6943SzhanglyGit  val busyCount = RegNext(RegNext(PopCount(oddTable)) + RegNext(PopCount(evenTable)))
170bc7d6943SzhanglyGit
1710030d978SzhanglyGit  XSPerfAccumulate("busy_count", PopCount(table))
172cd365d4cSrvcoresjw
1731ca0e4f3SYinan Xu  val perfEvents = Seq(
174e1a85e9fSchengguanghui    ("bt_std_freelist_1_4_valid", busyCount < (numPhyPregs / 4).U                                      ),
175e1a85e9fSchengguanghui    ("bt_std_freelist_2_4_valid", busyCount > (numPhyPregs / 4).U && busyCount <= (numPhyPregs / 2).U    ),
176e1a85e9fSchengguanghui    ("bt_std_freelist_3_4_valid", busyCount > (numPhyPregs / 2).U && busyCount <= (numPhyPregs * 3 / 4).U),
177e1a85e9fSchengguanghui    ("bt_std_freelist_4_4_valid", busyCount > (numPhyPregs * 3 / 4).U                                  )
1781ca0e4f3SYinan Xu  )
1791ca0e4f3SYinan Xu  generatePerfEvent()
180b034d3b9SLinJiawei}
181