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