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