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()) 338af95560SYinan Xu} 348af95560SYinan Xu 35bc7d6943SzhanglyGitclass BusyTable(numReadPorts: Int, numWritePorts: Int, numPhyPregs: Int, pregWB: PregWB)(implicit p: Parameters, params: SchdBlockParams) extends XSModule with HasPerfEvents { 36b034d3b9SLinJiawei val io = IO(new Bundle() { 37b034d3b9SLinJiawei // set preg state to busy 38b034d3b9SLinJiawei val allocPregs = Vec(RenameWidth, Flipped(ValidIO(UInt(PhyRegIdxWidth.W)))) 399aca92b9SYinan Xu // set preg state to ready (write back regfile + rob walk) 406624015fSLinJiawei val wbPregs = Vec(numWritePorts, Flipped(ValidIO(UInt(PhyRegIdxWidth.W)))) 41bc7d6943SzhanglyGit // fast wakeup 42bc7d6943SzhanglyGit val wakeUp: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpInValidBundle) 43bc7d6943SzhanglyGit // cancelFromDatapath 44bc7d6943SzhanglyGit val cancel = Vec(backendParams.numExu, Flipped(ValidIO(new CancelSignal))) 45b034d3b9SLinJiawei // read preg state 468af95560SYinan Xu val read = Vec(numReadPorts, new BusyTableReadIO) 47b034d3b9SLinJiawei }) 48b034d3b9SLinJiawei 49bc7d6943SzhanglyGit val wakeUpReg = Reg(params.genIQWakeUpInValidBundle) 50*0030d978SzhanglyGit val table = RegInit(0.U(numPhyPregs.W)) 51*0030d978SzhanglyGit val tableUpdate = Wire(Vec(numPhyPregs, Bool())) 52e77096aeSHaojin Tang val wakeUpFilterLS = io.wakeUp.filter(x => 53e77096aeSHaojin Tang Seq("LDU0", "LDU1", "HYU0").map(x.bits.exuIdx != backendParams.getExuIdx(_)).reduce(_ && _) 54e77096aeSHaojin Tang ) // TODO 55767bd21fSLinJiawei 5660deaca2SLinJiawei def reqVecToMask(rVec: Vec[Valid[UInt]]): UInt = { 5760deaca2SLinJiawei ParallelOR(rVec.map(v => Mux(v.valid, UIntToOH(v.bits), 0.U))) 5860deaca2SLinJiawei } 5960deaca2SLinJiawei 6060deaca2SLinJiawei val wbMask = reqVecToMask(io.wbPregs) 6160deaca2SLinJiawei val allocMask = reqVecToMask(io.allocPregs) 62bc7d6943SzhanglyGit val wakeUpMask = pregWB match { 63148571c9SZiyue Zhang case _: IntWB => wakeUpFilterLS.map(x => Mux(x.valid && x.bits.rfWen && !x.bits.loadDependency.asUInt.orR, UIntToOH(x.bits.pdest), 0.U)).toSeq.fold(0.U)(_ | _) //TODO: dont implement "load -> wakeUp other -> wakeUp BusyTable" now 64148571c9SZiyue Zhang case _: VfWB => wakeUpFilterLS.map(x => Mux(x.valid && (x.bits.fpWen || x.bits.vecWen) && !x.bits.loadDependency.asUInt.orR, UIntToOH(x.bits.pdest), 0.U)).toSeq.fold(0.U)(_ | _) 657a96cc7fSHaojin Tang case _: NoWB => throw new IllegalArgumentException("NoWB is not permitted") 66bc7d6943SzhanglyGit } 67bc7d6943SzhanglyGit val cancelMask = pregWB match { 68148571c9SZiyue Zhang case _: IntWB => io.cancel.map(x => Mux(x.valid && x.bits.rfWen, UIntToOH(x.bits.pdest), 0.U)).fold(0.U)(_ | _) 69148571c9SZiyue 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)(_ | _) 707a96cc7fSHaojin Tang case _: NoWB => throw new IllegalArgumentException("NoWB is not permitted") 71a6ad6ca2SYinan Xu } 72d479a3a8SYinan Xu 73bc7d6943SzhanglyGit /* 74bc7d6943SzhanglyGit we can ensure that the following conditions are mutually exclusive 75*0030d978SzhanglyGit wakeUp and cancel (same pdest) may arrive at the same cycle 76bc7d6943SzhanglyGit for a pdest: 77*0030d978SzhanglyGit rename alloc => wakeUp / cancel => ... => wakeUp / cancel => wakeUp 78bc7d6943SzhanglyGit or 79bc7d6943SzhanglyGit rename alloc => wbMask //TODO we still need wbMask because wakeUp signal is partial now 80bc7d6943SzhanglyGit the bypass state lasts for a maximum of one cycle, cancel(=> busy) or else(=> regFile) 81bc7d6943SzhanglyGit */ 82bc7d6943SzhanglyGit tableUpdate.zipWithIndex.foreach{ case (update, idx) => 83*0030d978SzhanglyGit when(allocMask(idx) || cancelMask(idx)) { 84*0030d978SzhanglyGit update := true.B 85*0030d978SzhanglyGit }.elsewhen(wakeUpMask(idx) || wbMask(idx)) { 86*0030d978SzhanglyGit update := false.B 87bc7d6943SzhanglyGit }.otherwise { 88bc7d6943SzhanglyGit update := table(idx) 89bc7d6943SzhanglyGit } 90bc7d6943SzhanglyGit } 91bc7d6943SzhanglyGit 92bc7d6943SzhanglyGit io.read.foreach{ case res => 93*0030d978SzhanglyGit res.resp := !table(res.req) 94bc7d6943SzhanglyGit } 95bc7d6943SzhanglyGit 96*0030d978SzhanglyGit table := tableUpdate.asUInt 97bc7d6943SzhanglyGit wakeUpReg := io.wakeUp 98bc7d6943SzhanglyGit 99*0030d978SzhanglyGit val oddTable = table.asBools.zipWithIndex.filter(_._2 % 2 == 1).map(_._1) 100*0030d978SzhanglyGit val evenTable = table.asBools.zipWithIndex.filter(_._2 % 2 == 0).map(_._1) 101bc7d6943SzhanglyGit val busyCount = RegNext(RegNext(PopCount(oddTable)) + RegNext(PopCount(evenTable))) 102bc7d6943SzhanglyGit 103*0030d978SzhanglyGit XSPerfAccumulate("busy_count", PopCount(table)) 104cd365d4cSrvcoresjw 1051ca0e4f3SYinan Xu val perfEvents = Seq( 10639c59369SXuan Hu ("std_freelist_1_4_valid", busyCount < (numPhyPregs / 4).U ), 10739c59369SXuan Hu ("std_freelist_2_4_valid", busyCount > (numPhyPregs / 4).U && busyCount <= (numPhyPregs / 2).U ), 10839c59369SXuan Hu ("std_freelist_3_4_valid", busyCount > (numPhyPregs / 2).U && busyCount <= (numPhyPregs * 3 / 4).U), 10939c59369SXuan Hu ("std_freelist_4_4_valid", busyCount > (numPhyPregs * 3 / 4).U ) 1101ca0e4f3SYinan Xu ) 1111ca0e4f3SYinan Xu generatePerfEvent() 112b034d3b9SLinJiawei} 113