1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* Copyright (c) 2020-2021 Peng Cheng Laboratory 4* 5* XiangShan is licensed under Mulan PSL v2. 6* You can use this software according to the terms and conditions of the Mulan PSL v2. 7* You may obtain a copy of Mulan PSL v2 at: 8* http://license.coscl.org.cn/MulanPSL2 9* 10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13* 14* See the Mulan PSL v2 for more details. 15***************************************************************************************/ 16 17package xiangshan.backend.rename 18 19import org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import xiangshan._ 23import utils._ 24import utility._ 25import xiangshan.backend.Bundles._ 26import xiangshan.backend.datapath.WbConfig.{IntWB, VfWB, NoWB, PregWB} 27import xiangshan.backend.issue.SchdBlockParams 28import xiangshan.backend.datapath.{DataSource} 29 30class BusyTableReadIO(implicit p: Parameters) extends XSBundle { 31 val req = Input(UInt(PhyRegIdxWidth.W)) 32 val resp = Output(Bool()) 33} 34 35class BusyTable(numReadPorts: Int, numWritePorts: Int, numPhyPregs: Int, pregWB: PregWB)(implicit p: Parameters, params: SchdBlockParams) extends XSModule with HasPerfEvents { 36 val io = IO(new Bundle() { 37 // set preg state to busy 38 val allocPregs = Vec(RenameWidth, Flipped(ValidIO(UInt(PhyRegIdxWidth.W)))) 39 // set preg state to ready (write back regfile + rob walk) 40 val wbPregs = Vec(numWritePorts, Flipped(ValidIO(UInt(PhyRegIdxWidth.W)))) 41 // fast wakeup 42 val wakeUp: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpInValidBundle) 43 // cancelFromDatapath 44 val cancel = Vec(backendParams.numExu, Flipped(ValidIO(new CancelSignal))) 45 // read preg state 46 val read = Vec(numReadPorts, new BusyTableReadIO) 47 }) 48 49 val wakeUpReg = Reg(params.genIQWakeUpInValidBundle) 50 val table = RegInit(0.U(numPhyPregs.W)) 51 val tableUpdate = Wire(Vec(numPhyPregs, Bool())) 52 val wakeUpFilterLS = io.wakeUp.filter(x => 53 Seq("LDU0", "LDU1", "HYU0").map(x.bits.exuIdx != backendParams.getExuIdx(_)).reduce(_ && _) 54 ) // TODO 55 56 def reqVecToMask(rVec: Vec[Valid[UInt]]): UInt = { 57 ParallelOR(rVec.map(v => Mux(v.valid, UIntToOH(v.bits), 0.U))) 58 } 59 60 val wbMask = reqVecToMask(io.wbPregs) 61 val allocMask = reqVecToMask(io.allocPregs) 62 val wakeUpMask = pregWB match { 63 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 64 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)(_ | _) 65 case _: NoWB => throw new IllegalArgumentException("NoWB is not permitted") 66 } 67 val cancelMask = pregWB match { 68 case _: IntWB => io.cancel.map(x => Mux(x.valid && x.bits.rfWen, UIntToOH(x.bits.pdest), 0.U)).fold(0.U)(_ | _) 69 case _: VfWB => io.cancel.map(x => Mux(x.valid && (x.bits.fpWen || x.bits.vecWen), UIntToOH(x.bits.pdest), 0.U)).fold(0.U)(_ | _) 70 case _: NoWB => throw new IllegalArgumentException("NoWB is not permitted") 71 } 72 73 /* 74 we can ensure that the following conditions are mutually exclusive 75 wakeUp and cancel (same pdest) may arrive at the same cycle 76 for a pdest: 77 rename alloc => wakeUp / cancel => ... => wakeUp / cancel => wakeUp 78 or 79 rename alloc => wbMask //TODO we still need wbMask because wakeUp signal is partial now 80 the bypass state lasts for a maximum of one cycle, cancel(=> busy) or else(=> regFile) 81 */ 82 tableUpdate.zipWithIndex.foreach{ case (update, idx) => 83 when(allocMask(idx) || cancelMask(idx)) { 84 update := true.B 85 }.elsewhen(wakeUpMask(idx) || wbMask(idx)) { 86 update := false.B 87 }.otherwise { 88 update := table(idx) 89 } 90 } 91 92 io.read.foreach{ case res => 93 res.resp := !table(res.req) 94 } 95 96 table := tableUpdate.asUInt 97 wakeUpReg := io.wakeUp 98 99 val oddTable = table.asBools.zipWithIndex.filter(_._2 % 2 == 1).map(_._1) 100 val evenTable = table.asBools.zipWithIndex.filter(_._2 % 2 == 0).map(_._1) 101 val busyCount = RegNext(RegNext(PopCount(oddTable)) + RegNext(PopCount(evenTable))) 102 103 XSPerfAccumulate("busy_count", PopCount(table)) 104 105 val perfEvents = Seq( 106 ("std_freelist_1_4_valid", busyCount < (numPhyPregs / 4).U ), 107 ("std_freelist_2_4_valid", busyCount > (numPhyPregs / 4).U && busyCount <= (numPhyPregs / 2).U ), 108 ("std_freelist_3_4_valid", busyCount > (numPhyPregs / 2).U && busyCount <= (numPhyPregs * 3 / 4).U), 109 ("std_freelist_4_4_valid", busyCount > (numPhyPregs * 3 / 4).U ) 110 ) 111 generatePerfEvent() 112} 113