package xiangshan.backend.issue import chisel3._ import chisel3.util._ import utils.PipeWithFlush import xiangshan.backend.Bundles.{ExuInput, connectSamePort} import xiangshan.backend.exu.ExeUnitParams class MultiWakeupQueueIO[T <: Bundle, TFlush <: Data]( gen : ExuInput, lastGen : ExuInput, flushGen : TFlush, latWidth : Int, ) extends Bundle { class EnqBundle extends Bundle { val uop = Output(gen) val lat = Output(UInt(latWidth.W)) } val flush = Input(flushGen) val enq = Flipped(Valid(new EnqBundle)) val deq = Output(Valid(lastGen)) } class MultiWakeupQueue[T <: Bundle, TFlush <: Data]( val gen : ExuInput, val lastGen : ExuInput, val flushGen : TFlush, val latencySet: Set[Int], flushFunc : (ExuInput, TFlush, Int) => Bool, modificationFunc: ExuInput => ExuInput = { x: ExuInput => x }, lastConnectFunc: (ExuInput, ExuInput) => ExuInput, ) extends Module { require(latencySet.min >= 0) val io = IO(new MultiWakeupQueueIO(gen, lastGen, flushGen, log2Up(latencySet.max) + 1)) val pipes = latencySet.map(x => Module(new PipeWithFlush[T, TFlush](gen, flushGen, x, flushFunc, modificationFunc))).toSeq val pipesOut = Wire(Valid(gen)) val lastConnect = Reg(Valid(lastGen)) pipes.zip(latencySet).foreach { case (pipe, lat) => pipe.io.flush := io.flush pipe.io.enq.valid := io.enq.valid && io.enq.bits.lat === lat.U pipe.io.enq.bits := io.enq.bits.uop } private val pipesValidVec = VecInit(pipes.map(_.io.deq).zip(latencySet).map(_ match { case (deq, 0) => deq.valid case (deq, i) => deq.valid && !flushFunc(deq.bits, io.flush, i) })) private val pipesBitsVec = VecInit(pipes.map(_.io.deq.bits).zip(latencySet).map(_ match { case (deq, 0) => deq case (deq, i) => modificationFunc(deq) })) pipesOut.valid := pipesValidVec.asUInt.orR pipesOut.bits := Mux1H(pipesValidVec, pipesBitsVec) pipesOut.bits.rfWen .foreach(_ := pipesValidVec.zip(pipesBitsVec.map(_.rfWen .get)).map{case(valid,wen) => valid && wen}.reduce(_||_)) pipesOut.bits.fpWen .foreach(_ := pipesValidVec.zip(pipesBitsVec.map(_.fpWen .get)).map{case(valid,wen) => valid && wen}.reduce(_||_)) pipesOut.bits.vecWen.foreach(_ := pipesValidVec.zip(pipesBitsVec.map(_.vecWen.get)).map{case(valid,wen) => valid && wen}.reduce(_||_)) pipesOut.bits.v0Wen .foreach(_ := pipesValidVec.zip(pipesBitsVec.map(_.v0Wen .get)).map{case(valid,wen) => valid && wen}.reduce(_||_)) pipesOut.bits.vlWen .foreach(_ := pipesValidVec.zip(pipesBitsVec.map(_.vlWen .get)).map{case(valid,wen) => valid && wen}.reduce(_||_)) lastConnect.valid := pipesOut.valid lastConnect.bits := lastConnectFunc(pipesOut.bits, lastConnect.bits) io.deq.valid := lastConnect.valid io.deq.bits := lastConnect.bits assert(PopCount(pipesValidVec) <= 1.U, "PopCount(pipesValidVec) should be no more than 1") }