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