package xiangshan.backend.issue import org.chipsalliance.cde.config.Parameters import chisel3._ import chisel3.util._ import utils.MapUtils import xiangshan._ import xiangshan.backend.fu.FuType import xiangshan.backend.fu.vector.Utils import xiangshan.backend.issue.EntryBundles.RespType class FuBusyTableWrite(fuLatencyMap: Map[FuType.OHType, Int]) (implicit p: Parameters, iqParams: IssueBlockParams) extends XSModule { private val latencyValMax: Int = fuLatencyMap.values.fold(0)(_ max _) private val tableSize = latencyValMax + 1 val io = IO(new FuBusyTableWriteIO(latencyValMax)) val deqResp = io.in.deqResp val og0Resp = io.in.og0Resp val og1Resp = io.in.og1Resp // instance of FuBusyTable insists only when latencyValMax > 0 private val fuBusyTable = RegInit(0.U(tableSize.W)) private val fuBusyTableNext = Wire(UInt(tableSize.W)) fuBusyTable := fuBusyTableNext /** * Map[latency, Set[fuType]] */ private val latMappedFuTypeSet: Map[Int, Set[FuType.OHType]] = MapUtils.groupByValueUnique(fuLatencyMap) private val deqRespSuccess = deqResp.valid private val og0RespFail = og0Resp.valid private val og1RespFail = og1Resp.valid && RespType.isBlocked(og1Resp.bits.resp) private val deqRespMatchVec = getMatchVecFromResp(deqResp) private val og0RespMatchVec = getMatchVecFromResp(og0Resp) private val og1RespMatchVec = getMatchVecFromResp(og1Resp) def getMatchVecFromResp(resp: Valid[IssueQueueDeqRespBundle]) : Vec[Bool] = { VecInit((0 until tableSize).map { lat => Cat( latMappedFuTypeSet.getOrElse(lat, Set()).toSeq.sorted.map( fuType => resp.bits.fuType(fuType.id) ).toSeq ).orR }) } private val fuBusyTableShift = (fuBusyTable >> 1).asUInt private val deqRespSetShift = Mux(deqRespSuccess, deqRespMatchVec.asUInt >> 1, Utils.NZeros(tableSize)) private val og0RespClearShift = Mux(og0RespFail, og0RespMatchVec.asUInt >> 2, Utils.NZeros(tableSize)) private val og1RespClearShift = Mux(og1RespFail, og1RespMatchVec.asUInt >> 3, Utils.NZeros(tableSize)) // Just for more readable verilog if(backendParams.debugEn) { dontTouch(fuBusyTableShift) dontTouch(deqRespSetShift) dontTouch(og0RespClearShift) dontTouch(og1RespClearShift) } fuBusyTableNext := fuBusyTableShift & (~og0RespClearShift).asUInt & (~og1RespClearShift).asUInt | deqRespSetShift.asUInt io.out.fuBusyTable := fuBusyTable io.out.deqRespSet := Mux(deqRespSuccess, deqRespMatchVec.asUInt, Utils.NZeros(tableSize)).asUInt } class FuBusyTableWriteIO(latencyValMax: Int)(implicit p: Parameters, iqParams: IssueBlockParams) extends XSBundle { private val tableSize = latencyValMax + 1 val in = new Bundle { val deqResp = Flipped(ValidIO(new IssueQueueDeqRespBundle)) val og0Resp = Flipped(ValidIO(new IssueQueueDeqRespBundle)) val og1Resp = Flipped(ValidIO(new IssueQueueDeqRespBundle)) } val out = new Bundle { val fuBusyTable = Output(UInt(tableSize.W)) val deqRespSet = Output(UInt(tableSize.W)) } }