xref: /XiangShan/src/main/scala/xiangshan/backend/PipeGroupConnect.scala (revision 1c6572a60e0280d38a76fba88d647f136635e60c)
1package xiangshan.backend
2
3import chisel3._
4import chisel3.util._
5
6class PipeGroupConnect[T <: Data](n: Int, gen: => T) extends Module {
7  val io = IO(new Bundle {
8    val in = Vec(n, Flipped(DecoupledIO(gen)))
9    val out = Vec(n, DecoupledIO(gen))
10    val flush = Input(Bool())
11    val outAllFire = Input(Bool())
12  })
13
14  // Input Alias
15  // Use private[this] to limit the wrong usage for not IO hardware in object with the same name.
16  private[this] val flush = io.flush
17  private[this] val inValidSeq  = io.in.map(_.valid)
18  private[this] val inDataSeq   = io.in.map(_.bits)
19  private[this] val outReadySeq = io.out.map(_.ready)
20
21  // Regs
22  private[this] val validVec = RegInit(VecInit.fill(n)(false.B))
23  private[this] val dataVec  = Reg(Vec(n, gen))
24
25  // Logic
26  private[this] val valids    = Cat(validVec.reverse)
27  private[this] val inValids  = Cat(inValidSeq.reverse)
28  private[this] val outReadys = Cat(outReadySeq.reverse)
29
30  // Todo: canAccVec for each elem
31  // Todo: no outReadys version for better timing and lower performance
32  private[this] val canAcc = io.outAllFire || !valids.orR
33
34  (validVec zip inValids.asBools zip outReadys.asBools).foreach { case ((valid, inValid), outReady) =>
35    valid := MuxCase(
36      default = valid /*keep*/,
37      Seq(
38        flush               -> false.B,
39        (inValid && canAcc) -> true.B,
40        outReady            -> false.B
41      )
42    )
43  }
44
45  (dataVec zip inValids.asBools zip inDataSeq).foreach { case ((data, inValid), inData) =>
46    when (inValid && canAcc) {
47      data := inData
48    }
49  }
50
51  // Output connections
52  for (i <- 0 until n) {
53    io.in(i).ready  := canAcc
54    io.out(i).valid := validVec(i)
55    io.out(i).bits  := dataVec(i)
56  }
57}
58
59object PipeGroupConnect {
60  def apply[T <: Data](
61    // Left can be not Vec, but right must be Vec
62    left: Seq[DecoupledIO[T]],
63    right: Vec[DecoupledIO[T]],
64    flush: Bool,
65    rightAllFire: Bool,
66    suggestName: String = null,
67  ): Unit =  {
68    require(left.size == right.size, "The sizes of left and right Vec Bundle should be equal in PipeGroupConnect")
69    require(left.size > 0, "The size of Vec Bundle in PipeGroupConnect should be more than 0")
70    val mod = Module(new PipeGroupConnect(left.size, chiselTypeOf(left.head.bits)))
71    mod.io.flush := flush
72    mod.io.in.zipWithIndex.foreach { case (in, i) =>
73      in.valid := left(i).valid
74      in.bits := left(i).bits
75      left(i).ready := in.ready
76    }
77    mod.io.outAllFire := rightAllFire
78    right <> mod.io.out
79
80    if (suggestName != null)
81      mod.suggestName(suggestName)
82  }
83}
84