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