xref: /XiangShan/src/main/scala/xiangshan/backend/issue/FuBusyTableWrite.scala (revision 6c996d9ba0d49ea843030ebedde0b5300a7f5ef0)
1package xiangshan.backend.issue
2
3import chipsalliance.rocketchip.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[Int, 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[Int]] = MapUtils.groupByValueUnique(fuLatencyMap)
31
32  private val deqRespSuccess = deqResp.valid && deqResp.bits.respType === RSFeedbackType.issueSuccess
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.U
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  dontTouch(fuBusyTableShift)
58  dontTouch(deqRespSetShift)
59  dontTouch(og0RespClearShift)
60  dontTouch(og1RespClearShift)
61
62  fuBusyTableNext := fuBusyTableShift & (~og0RespClearShift).asUInt & (~og1RespClearShift).asUInt | deqRespSetShift.asUInt
63
64  io.out.fuBusyTable := fuBusyTable
65  io.out.deqRespSet := Mux(deqRespSuccess, deqRespMatchVec.asUInt, Utils.NZeros(tableSize)).asUInt
66}
67
68class FuBusyTableWriteIO(latencyValMax: Int)(implicit p: Parameters, iqParams: IssueBlockParams) extends XSBundle {
69  private val tableSize = latencyValMax + 1
70  val in = new Bundle {
71    val deqResp =  Flipped(ValidIO(new IssueQueueDeqRespBundle))
72    val og0Resp = Flipped(ValidIO(new IssueQueueDeqRespBundle))
73    val og1Resp = Flipped(ValidIO(new IssueQueueDeqRespBundle))
74  }
75  val out = new Bundle {
76    val fuBusyTable = Output(UInt(tableSize.W))
77    val deqRespSet = Output(UInt(tableSize.W))
78  }
79}