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 tableUpdate = Wire(Vec(numPhyPregs, Bool())) 5513551487SzhanglyGit val wakeupOHVec = Wire(Vec(numPhyPregs, UInt(io.wakeUp.size.W))) 56767bd21fSLinJiawei 5760deaca2SLinJiawei def reqVecToMask(rVec: Vec[Valid[UInt]]): UInt = { 5860deaca2SLinJiawei ParallelOR(rVec.map(v => Mux(v.valid, UIntToOH(v.bits), 0.U))) 5960deaca2SLinJiawei } 6060deaca2SLinJiawei 6113551487SzhanglyGit shiftLoadDependency.zip(io.wakeUp.map(_.bits.loadDependency)).zip(params.wakeUpInExuSources.map(_.name)).foreach { 6213551487SzhanglyGit case ((deps, originalDeps), name) => deps.zip(originalDeps).zipWithIndex.foreach { 6313551487SzhanglyGit case ((dep, originalDep), deqPortIdx) => 6413551487SzhanglyGit // TODO: getLdExuIdx 6580c686d5SzhanglyGit if (params.backendParam.getLdExuIdx(params.backendParam.allExuParams.find(_.name == name).get) == deqPortIdx) 6613551487SzhanglyGit dep := (originalDep << 2).asUInt | 2.U 6713551487SzhanglyGit else 6813551487SzhanglyGit dep := originalDep << 1 6913551487SzhanglyGit } 7013551487SzhanglyGit } 7113551487SzhanglyGit 7213551487SzhanglyGit wakeupOHVec.zipWithIndex.foreach{ case (wakeupOH, idx) => 7313551487SzhanglyGit val tmp = pregWB match { 7413551487SzhanglyGit case _: IntWB => io.wakeUp.map(x => x.valid && x.bits.rfWen && UIntToOH(x.bits.pdest)(idx) && !LoadShouldCancel(Some(x.bits.loadDependency), io.ldCancel)) 7513551487SzhanglyGit 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)) 7613551487SzhanglyGit } 77ff3fcdf1Sxiaofeibao-xjtu wakeupOH := (if (io.wakeUp.nonEmpty) VecInit(tmp.toSeq).asUInt else 0.U) 7813551487SzhanglyGit } 7960deaca2SLinJiawei val wbMask = reqVecToMask(io.wbPregs) 8060deaca2SLinJiawei val allocMask = reqVecToMask(io.allocPregs) 8113551487SzhanglyGit val wakeUpMask = VecInit(wakeupOHVec.map(_.orR).toSeq).asUInt 82bc7d6943SzhanglyGit val cancelMask = pregWB match { 83148571c9SZiyue Zhang case _: IntWB => io.cancel.map(x => Mux(x.valid && x.bits.rfWen, UIntToOH(x.bits.pdest), 0.U)).fold(0.U)(_ | _) 84148571c9SZiyue 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)(_ | _) 857a96cc7fSHaojin Tang case _: NoWB => throw new IllegalArgumentException("NoWB is not permitted") 86a6ad6ca2SYinan Xu } 8713551487SzhanglyGit val ldCancelMask = loadDependency.map(x => LoadShouldCancel(Some(x), io.ldCancel)) 8813551487SzhanglyGit 8913551487SzhanglyGit loadDependency.zipWithIndex.foreach{ case (ldDp, idx) => 9013551487SzhanglyGit when(allocMask(idx) || cancelMask(idx) || wbMask(idx) || ldCancelMask(idx)) { 9113551487SzhanglyGit ldDp := 0.U.asTypeOf(ldDp) 9213551487SzhanglyGit }.elsewhen(wakeUpMask(idx)) { 93ff3fcdf1Sxiaofeibao-xjtu ldDp := (if (io.wakeUp.nonEmpty) Mux1H(wakeupOHVec(idx), shiftLoadDependency) else 0.U.asTypeOf(ldDp)) 94*41dbbdfdSsinceforYy }.elsewhen(ldDp.map(x => x.orR).reduce(_ | _)) { 9513551487SzhanglyGit ldDp := VecInit(ldDp.map(x => x(x.getWidth - 2, 0) << 1)) 9613551487SzhanglyGit } 9713551487SzhanglyGit } 98d479a3a8SYinan Xu 99bc7d6943SzhanglyGit /* 100bc7d6943SzhanglyGit we can ensure that the following conditions are mutually exclusive 1010030d978SzhanglyGit wakeUp and cancel (same pdest) may arrive at the same cycle 102bc7d6943SzhanglyGit for a pdest: 1030030d978SzhanglyGit rename alloc => wakeUp / cancel => ... => wakeUp / cancel => wakeUp 104bc7d6943SzhanglyGit or 105bc7d6943SzhanglyGit rename alloc => wbMask //TODO we still need wbMask because wakeUp signal is partial now 106bc7d6943SzhanglyGit the bypass state lasts for a maximum of one cycle, cancel(=> busy) or else(=> regFile) 107bc7d6943SzhanglyGit */ 108*41dbbdfdSsinceforYy val table = VecInit((0 until numPhyPregs).zip(tableUpdate).map{ case (idx, update) => 109*41dbbdfdSsinceforYy RegEnable(update, 0.U(1.W), allocMask(idx) || cancelMask(idx) || ldCancelMask(idx) || wakeUpMask(idx) || wbMask(idx)) 110*41dbbdfdSsinceforYy }).asUInt 111*41dbbdfdSsinceforYy 112bc7d6943SzhanglyGit tableUpdate.zipWithIndex.foreach{ case (update, idx) => 11313551487SzhanglyGit when(allocMask(idx) || cancelMask(idx) || ldCancelMask(idx)) { 11413551487SzhanglyGit update := true.B //busy 1150030d978SzhanglyGit }.elsewhen(wakeUpMask(idx) || wbMask(idx)) { 11613551487SzhanglyGit update := false.B //ready 117bc7d6943SzhanglyGit }.otherwise { 118bc7d6943SzhanglyGit update := table(idx) 119bc7d6943SzhanglyGit } 120bc7d6943SzhanglyGit } 121bc7d6943SzhanglyGit 122bc7d6943SzhanglyGit io.read.foreach{ case res => 1230030d978SzhanglyGit res.resp := !table(res.req) 12413551487SzhanglyGit res.loadDependency := loadDependency(res.req) 125bc7d6943SzhanglyGit } 126bc7d6943SzhanglyGit 1270030d978SzhanglyGit val oddTable = table.asBools.zipWithIndex.filter(_._2 % 2 == 1).map(_._1) 1280030d978SzhanglyGit val evenTable = table.asBools.zipWithIndex.filter(_._2 % 2 == 0).map(_._1) 129bc7d6943SzhanglyGit val busyCount = RegNext(RegNext(PopCount(oddTable)) + RegNext(PopCount(evenTable))) 130bc7d6943SzhanglyGit 1310030d978SzhanglyGit XSPerfAccumulate("busy_count", PopCount(table)) 132cd365d4cSrvcoresjw 1331ca0e4f3SYinan Xu val perfEvents = Seq( 13439c59369SXuan Hu ("std_freelist_1_4_valid", busyCount < (numPhyPregs / 4).U ), 13539c59369SXuan Hu ("std_freelist_2_4_valid", busyCount > (numPhyPregs / 4).U && busyCount <= (numPhyPregs / 2).U ), 13639c59369SXuan Hu ("std_freelist_3_4_valid", busyCount > (numPhyPregs / 2).U && busyCount <= (numPhyPregs * 3 / 4).U), 13739c59369SXuan Hu ("std_freelist_4_4_valid", busyCount > (numPhyPregs * 3 / 4).U ) 1381ca0e4f3SYinan Xu ) 1391ca0e4f3SYinan Xu generatePerfEvent() 140b034d3b9SLinJiawei} 141