xref: /XiangShan/src/main/scala/xiangshan/backend/rename/BusyTable.scala (revision ff3fcdf11874ffacafd64ec81fd1c4893f58150b)
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._
267a96cc7fSHaojin Tangimport xiangshan.backend.datapath.WbConfig.{IntWB, VfWB, NoWB, PregWB}
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())
3313551487SzhanglyGit  val loadDependency = Vec(LoadPipelineWidth, Output(UInt(3.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
45bc7d6943SzhanglyGit    val cancel = Vec(backendParams.numExu, Flipped(ValidIO(new CancelSignal)))
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
5213551487SzhanglyGit  val loadDependency = RegInit(0.U.asTypeOf(Vec(numPhyPregs, Vec(LoadPipelineWidth, UInt(3.W)))))
5313551487SzhanglyGit  val shiftLoadDependency = Wire(Vec(io.wakeUp.size, Vec(LoadPipelineWidth, UInt(3.W))))
540030d978SzhanglyGit  val table = RegInit(0.U(numPhyPregs.W))
550030d978SzhanglyGit  val tableUpdate = Wire(Vec(numPhyPregs, Bool()))
5613551487SzhanglyGit  val wakeupOHVec = Wire(Vec(numPhyPregs, UInt(io.wakeUp.size.W)))
57767bd21fSLinJiawei
5860deaca2SLinJiawei  def reqVecToMask(rVec: Vec[Valid[UInt]]): UInt = {
5960deaca2SLinJiawei    ParallelOR(rVec.map(v => Mux(v.valid, UIntToOH(v.bits), 0.U)))
6060deaca2SLinJiawei  }
6160deaca2SLinJiawei
6213551487SzhanglyGit  shiftLoadDependency.zip(io.wakeUp.map(_.bits.loadDependency)).zip(params.wakeUpInExuSources.map(_.name)).foreach {
6313551487SzhanglyGit    case ((deps, originalDeps), name) => deps.zip(originalDeps).zipWithIndex.foreach {
6413551487SzhanglyGit      case ((dep, originalDep), deqPortIdx) =>
6513551487SzhanglyGit        // TODO: getLdExuIdx
6613551487SzhanglyGit        if (name.contains("LDU") && name.replace("LDU", "").toInt == deqPortIdx)
6713551487SzhanglyGit          dep := (originalDep << 2).asUInt | 2.U
6813551487SzhanglyGit        else
6913551487SzhanglyGit          dep := originalDep << 1
7013551487SzhanglyGit    }
7113551487SzhanglyGit  }
7213551487SzhanglyGit
7313551487SzhanglyGit  wakeupOHVec.zipWithIndex.foreach{ case (wakeupOH, idx) =>
7413551487SzhanglyGit    val tmp = pregWB match {
7513551487SzhanglyGit      case _: IntWB => io.wakeUp.map(x => x.valid && x.bits.rfWen && UIntToOH(x.bits.pdest)(idx) && !LoadShouldCancel(Some(x.bits.loadDependency), io.ldCancel))
7613551487SzhanglyGit      case _: VfWB => io.wakeUp.map(x => x.valid && (x.bits.fpWen || x.bits.vecWen) && UIntToOH(x.bits.pdest)(idx) && !LoadShouldCancel(Some(x.bits.loadDependency), io.ldCancel))
7713551487SzhanglyGit    }
78*ff3fcdf1Sxiaofeibao-xjtu    wakeupOH := (if (io.wakeUp.nonEmpty) VecInit(tmp.toSeq).asUInt else 0.U)
7913551487SzhanglyGit  }
8060deaca2SLinJiawei  val wbMask = reqVecToMask(io.wbPregs)
8160deaca2SLinJiawei  val allocMask = reqVecToMask(io.allocPregs)
8213551487SzhanglyGit  val wakeUpMask = VecInit(wakeupOHVec.map(_.orR).toSeq).asUInt
83bc7d6943SzhanglyGit  val cancelMask = pregWB match {
84148571c9SZiyue Zhang    case _: IntWB => io.cancel.map(x => Mux(x.valid && x.bits.rfWen, UIntToOH(x.bits.pdest), 0.U)).fold(0.U)(_ | _)
85148571c9SZiyue Zhang    case _: VfWB => io.cancel.map(x => Mux(x.valid && (x.bits.fpWen || x.bits.vecWen), UIntToOH(x.bits.pdest), 0.U)).fold(0.U)(_ | _)
867a96cc7fSHaojin Tang    case _: NoWB => throw new IllegalArgumentException("NoWB is not permitted")
87a6ad6ca2SYinan Xu  }
8813551487SzhanglyGit  val ldCancelMask = loadDependency.map(x => LoadShouldCancel(Some(x), io.ldCancel))
8913551487SzhanglyGit
9013551487SzhanglyGit  loadDependency.zipWithIndex.foreach{ case (ldDp, idx) =>
9113551487SzhanglyGit    when(allocMask(idx) || cancelMask(idx) || wbMask(idx) || ldCancelMask(idx)) {
9213551487SzhanglyGit      ldDp := 0.U.asTypeOf(ldDp)
9313551487SzhanglyGit    }.elsewhen(wakeUpMask(idx)) {
94*ff3fcdf1Sxiaofeibao-xjtu      ldDp := (if (io.wakeUp.nonEmpty) Mux1H(wakeupOHVec(idx), shiftLoadDependency) else 0.U.asTypeOf(ldDp))
9513551487SzhanglyGit    }.otherwise {
9613551487SzhanglyGit      ldDp := VecInit(ldDp.map(x => x(x.getWidth - 2, 0) << 1))
9713551487SzhanglyGit    }
9813551487SzhanglyGit  }
99d479a3a8SYinan Xu
100bc7d6943SzhanglyGit  /*
101bc7d6943SzhanglyGit  we can ensure that the following conditions are mutually exclusive
1020030d978SzhanglyGit  wakeUp and cancel (same pdest) may arrive at the same cycle
103bc7d6943SzhanglyGit  for a pdest:
1040030d978SzhanglyGit    rename alloc => wakeUp / cancel => ... => wakeUp / cancel => wakeUp
105bc7d6943SzhanglyGit  or
106bc7d6943SzhanglyGit    rename alloc => wbMask  //TODO we still need wbMask because wakeUp signal is partial now
107bc7d6943SzhanglyGit  the bypass state lasts for a maximum of one cycle, cancel(=> busy) or else(=> regFile)
108bc7d6943SzhanglyGit   */
109bc7d6943SzhanglyGit  tableUpdate.zipWithIndex.foreach{ case (update, idx) =>
11013551487SzhanglyGit    when(allocMask(idx) || cancelMask(idx) || ldCancelMask(idx)) {
11113551487SzhanglyGit      update := true.B                                    //busy
1120030d978SzhanglyGit    }.elsewhen(wakeUpMask(idx) || wbMask(idx)) {
11313551487SzhanglyGit      update := false.B                                   //ready
114bc7d6943SzhanglyGit    }.otherwise {
115bc7d6943SzhanglyGit      update := table(idx)
116bc7d6943SzhanglyGit    }
117bc7d6943SzhanglyGit  }
118bc7d6943SzhanglyGit
119bc7d6943SzhanglyGit  io.read.foreach{ case res =>
1200030d978SzhanglyGit    res.resp := !table(res.req)
12113551487SzhanglyGit    res.loadDependency := loadDependency(res.req)
122bc7d6943SzhanglyGit  }
123bc7d6943SzhanglyGit
1240030d978SzhanglyGit  table := tableUpdate.asUInt
125bc7d6943SzhanglyGit
1260030d978SzhanglyGit  val oddTable = table.asBools.zipWithIndex.filter(_._2 % 2 == 1).map(_._1)
1270030d978SzhanglyGit  val evenTable = table.asBools.zipWithIndex.filter(_._2 % 2 == 0).map(_._1)
128bc7d6943SzhanglyGit  val busyCount = RegNext(RegNext(PopCount(oddTable)) + RegNext(PopCount(evenTable)))
129bc7d6943SzhanglyGit
1300030d978SzhanglyGit  XSPerfAccumulate("busy_count", PopCount(table))
131cd365d4cSrvcoresjw
1321ca0e4f3SYinan Xu  val perfEvents = Seq(
13339c59369SXuan Hu    ("std_freelist_1_4_valid", busyCount < (numPhyPregs / 4).U                                      ),
13439c59369SXuan Hu    ("std_freelist_2_4_valid", busyCount > (numPhyPregs / 4).U && busyCount <= (numPhyPregs / 2).U    ),
13539c59369SXuan Hu    ("std_freelist_3_4_valid", busyCount > (numPhyPregs / 2).U && busyCount <= (numPhyPregs * 3 / 4).U),
13639c59369SXuan Hu    ("std_freelist_4_4_valid", busyCount > (numPhyPregs * 3 / 4).U                                  )
1371ca0e4f3SYinan Xu  )
1381ca0e4f3SYinan Xu  generatePerfEvent()
139b034d3b9SLinJiawei}
140