xref: /XiangShan/src/main/scala/xiangshan/backend/issue/MultiWakeupQueue.scala (revision 493a9370f60904d83af4f1555d40709cba1f5ef1)
1package xiangshan.backend.issue
2
3import chisel3._
4import chisel3.util._
5import utils.PipeWithFlush
6
7class MultiWakeupQueueIO[T <: Data, TFlush <: Data](
8  gen       : T,
9  flushGen  : TFlush,
10  latWidth  : Int,
11) extends Bundle {
12  class EnqBundle extends Bundle {
13    val uop = Output(gen)
14    val lat = Output(UInt(latWidth.W))
15  }
16
17  val flush = Input(flushGen)
18  val enq = Flipped(Valid(new EnqBundle))
19  val og0IssueFail = Input(Bool())
20  val og1IssueFail = Input(Bool())
21  val deq = Output(Valid(gen))
22}
23
24class MultiWakeupQueue[T <: Data, TFlush <: Data](
25  val gen       : T,
26  val flushGen  : TFlush,
27  val latencySet: Set[Int],
28  flushFunc : (T, TFlush, Int) => Bool
29) extends Module {
30  require(latencySet.min >= 0)
31
32  val io = IO(new MultiWakeupQueueIO(gen, flushGen, log2Up(latencySet.max) + 1))
33
34  val pipes = latencySet.map(x => Module(new PipeWithFlush[T, TFlush](gen, flushGen, x, flushFunc))).toSeq
35
36  pipes.zip(latencySet).foreach {
37    case (pipe, lat) =>
38      pipe.io.flush := io.flush
39      pipe.io.enq.valid := io.enq.valid && io.enq.bits.lat === lat.U
40      pipe.io.enq.bits := io.enq.bits.uop
41  }
42
43  private val pipesValidVec = VecInit(pipes.map(_.io.deq.valid).zip(latencySet).map(_ match {
44    case (valid, 1) => valid && !io.og0IssueFail
45    case (valid, 2) => valid && !io.og1IssueFail
46    case (valid, _) => valid
47  }))
48  private val pipesBitsVec = VecInit(pipes.map(_.io.deq.bits))
49
50  io.deq.valid := pipesValidVec.asUInt.orR
51  io.deq.bits := Mux1H(pipesValidVec, pipesBitsVec)
52
53  assert(PopCount(pipesValidVec) <= 1.U, "PopCount(pipesValidVec) should be no more than 1")
54}
55