xref: /XiangShan/src/main/scala/xiangshan/backend/issue/FuBusyTableWrite.scala (revision 0c7ebb58175b51109677230e8cbab09e73166956)
1package xiangshan.backend.issue
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import utils.MapUtils
7import xiangshan._
8import xiangshan.backend.fu.FuType
9import xiangshan.backend.fu.vector.Utils
10
11class FuBusyTableWrite(fuLatencyMap: Map[FuType.OHType, Int]) (implicit p: Parameters, iqParams: IssueBlockParams) extends XSModule {
12  private val latencyValMax: Int = fuLatencyMap.values.fold(0)(_ max _)
13  private val tableSize = latencyValMax + 1
14  val io = IO(new FuBusyTableWriteIO(latencyValMax))
15
16  val deqResp = io.in.deqResp
17  val og0Resp = io.in.og0Resp
18  val og1Resp = io.in.og1Resp
19
20  // instance of FuBusyTable insists only when latencyValMax > 0
21  private val fuBusyTable = RegInit(0.U(tableSize.W))
22
23  private val fuBusyTableNext = Wire(UInt(tableSize.W))
24
25  fuBusyTable := fuBusyTableNext
26
27  /**
28    * Map[latency, Set[fuType]]
29    */
30  private val latMappedFuTypeSet: Map[Int, Set[FuType.OHType]] = MapUtils.groupByValueUnique(fuLatencyMap)
31
32  private val deqRespSuccess = deqResp.valid
33  private val og0RespFail = og0Resp.valid && og0Resp.bits.respType === RSFeedbackType.rfArbitFail
34  private val og1RespFail = og1Resp.valid && og1Resp.bits.respType === RSFeedbackType.fuBusy
35
36  private val deqRespMatchVec = getMatchVecFromResp(deqResp)
37  private val og0RespMatchVec = getMatchVecFromResp(og0Resp)
38  private val og1RespMatchVec = getMatchVecFromResp(og1Resp)
39
40  def getMatchVecFromResp(resp: Valid[IssueQueueDeqRespBundle]) : Vec[Bool] = {
41    VecInit((0 until tableSize).map {
42      lat =>
43        Cat(
44          latMappedFuTypeSet.getOrElse(lat, Set()).map(
45            fuType => resp.bits.fuType(fuType.id)
46          ).toSeq
47        ).orR
48    })
49  }
50
51  private val fuBusyTableShift = (fuBusyTable >> 1).asUInt
52  private val deqRespSetShift = Mux(deqRespSuccess, deqRespMatchVec.asUInt >> 1, Utils.NZeros(tableSize))
53  private val og0RespClearShift = Mux(og0RespFail, og0RespMatchVec.asUInt >> 2, Utils.NZeros(tableSize))
54  private val og1RespClearShift = Mux(og1RespFail, og1RespMatchVec.asUInt >> 3, Utils.NZeros(tableSize))
55
56  // Just for more readable verilog
57  if(backendParams.debugEn) {
58    dontTouch(fuBusyTableShift)
59    dontTouch(deqRespSetShift)
60    dontTouch(og0RespClearShift)
61    dontTouch(og1RespClearShift)
62  }
63
64  fuBusyTableNext := fuBusyTableShift & (~og0RespClearShift).asUInt & (~og1RespClearShift).asUInt | deqRespSetShift.asUInt
65
66  io.out.fuBusyTable := fuBusyTable
67  io.out.deqRespSet := Mux(deqRespSuccess, deqRespMatchVec.asUInt, Utils.NZeros(tableSize)).asUInt
68}
69
70class FuBusyTableWriteIO(latencyValMax: Int)(implicit p: Parameters, iqParams: IssueBlockParams) extends XSBundle {
71  private val tableSize = latencyValMax + 1
72  val in = new Bundle {
73    val deqResp =  Flipped(ValidIO(new IssueQueueDeqRespBundle))
74    val og0Resp = Flipped(ValidIO(new IssueQueueDeqRespBundle))
75    val og1Resp = Flipped(ValidIO(new IssueQueueDeqRespBundle))
76  }
77  val out = new Bundle {
78    val fuBusyTable = Output(UInt(tableSize.W))
79    val deqRespSet = Output(UInt(tableSize.W))
80  }
81}