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