xref: /XiangShan/src/main/scala/utils/PipeWithFlush.scala (revision 0c7ebb58175b51109677230e8cbab09e73166956)
1package utils
2
3import chisel3._
4import chisel3.util._
5import xiangshan._
6
7/** Pipeline module generator parameterized by data type and latency.
8  *
9  * @param gen a Chisel type, used as data in pipe
10  * @param flushGen a Chisel type, used as flush signal
11  * @param latency the number of pipeline stages
12  * @param flushFunc used to generate flush signal
13  * @tparam T Type of [[io.enq.bits]] and [[io.deq.bits]]
14  * @tparam TFlush Type of [[io.flush]]
15  */
16class PipeWithFlush[T <: Data, TFlush <: Data] (
17  gen: T,
18  lastGen: T,
19  flushGen: TFlush,
20  latency: Int,
21  flushFunc: (T, TFlush, Int) => Bool,
22  modificationFunc: (T, T) => T
23) extends Module {
24  require(latency >= 0, "Pipe latency must be greater than or equal to zero!")
25
26  class PipeIO extends Bundle {
27    val flush = Input(flushGen)
28    val enq = Input(Valid(gen))
29    val deq = Output(Valid(lastGen))
30  }
31
32  val io = IO(new PipeIO)
33
34  val valids: Seq[Bool] = io.enq.valid +: Seq.fill(latency)(RegInit(false.B))
35  val bits: Seq[T] = io.enq.bits +: Seq.fill(latency-1)(Reg(gen)) ++: Seq.fill(1)(Reg(lastGen))
36  val nextBits: Seq[T] = bits.tail :+ bits.last
37  val modifiedBits: Seq[T] = bits.zip(nextBits).map{case (last, next) => modificationFunc(last, next)}
38
39  for (i <- 0 until latency) {
40    valids(i + 1) := valids(i) && !flushFunc(bits(i), io.flush, i)
41    when (valids(i)) {
42      bits(i + 1) := modifiedBits(i)
43    }
44  }
45  io.deq.valid := valids.last
46  io.deq.bits := bits.last
47}
48