diff options
| author | anniej-sifive | 2021-08-03 16:09:19 -0700 |
|---|---|---|
| committer | GitHub | 2021-08-03 16:09:19 -0700 |
| commit | da923f317ff325a93cee6289552ccfa413c35f98 (patch) | |
| tree | 59f30f6d3e11bc5fb533eafe163c255525885915 /src/main | |
| parent | 1e7829eb674eed85a4cd537896d9fd9ee0bc5ff4 (diff) | |
Added flush capability to Queue (#2030)
Co-authored-by: Megan Wachs <megan@sifive.com>
Co-authored-by: Deborah Soung <debs@sifive.com>
Diffstat (limited to 'src/main')
| -rw-r--r-- | src/main/scala/chisel3/util/Decoupled.scala | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 33682020..8909ffe3 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -163,8 +163,9 @@ object DeqIO { /** An I/O Bundle for Queues * @param gen The type of data to queue * @param entries The max number of entries in the queue. + * @param hasFlush A boolean for whether the generated Queue is flushable */ -class QueueIO[T <: Data](private val gen: T, val entries: Int) extends Bundle +class QueueIO[T <: Data](private val gen: T, val entries: Int, val hasFlush: Boolean = false) extends Bundle { // See github.com/freechipsproject/chisel3/issues/765 for why gen is a private val and proposed replacement APIs. /* These may look inverted, because the names (enq/deq) are from the perspective of the client, @@ -177,6 +178,9 @@ class QueueIO[T <: Data](private val gen: T, val entries: Int) extends Bundle val deq = Flipped(DeqIO(gen)) /** The current amount of data in the queue */ val count = Output(UInt(log2Ceil(entries + 1).W)) + /** When asserted, reset the enqueue and dequeue pointers, effectively flushing the queue (Optional IO for a flushable Queue)*/ + val flush = if (hasFlush) Some(Input(Bool())) else None + } /** A hardware module implementing a Queue @@ -187,7 +191,7 @@ class QueueIO[T <: Data](private val gen: T, val entries: Int) extends Bundle * @param flow True if the inputs can be consumed on the same cycle (the inputs "flow" through the queue immediately). * The ''valid'' signals are coupled. * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element. - * + * @param hasFlush True if generated queue requires a flush feature * @example {{{ * val q = Module(new Queue(UInt(), 16)) * q.io.enq <> producer.io.out @@ -199,7 +203,8 @@ class Queue[T <: Data](val gen: T, val entries: Int, val pipe: Boolean = false, val flow: Boolean = false, - val useSyncReadMem: Boolean = false) + val useSyncReadMem: Boolean = false, + val hasFlush: Boolean = false) (implicit compileOptions: chisel3.CompileOptions) extends Module() { require(entries > -1, "Queue must have non-negative number of entries") @@ -215,19 +220,20 @@ class Queue[T <: Data](val gen: T, } } - val io = IO(new QueueIO(genType, entries)) - + val io = IO(new QueueIO(genType, entries, hasFlush)) val ram = if (useSyncReadMem) SyncReadMem(entries, genType, SyncReadMem.WriteFirst) else Mem(entries, genType) val enq_ptr = Counter(entries) val deq_ptr = Counter(entries) val maybe_full = RegInit(false.B) - val ptr_match = enq_ptr.value === deq_ptr.value val empty = ptr_match && !maybe_full val full = ptr_match && maybe_full val do_enq = WireDefault(io.enq.fire()) val do_deq = WireDefault(io.deq.fire()) + val flush = io.flush.getOrElse(false.B) + // when flush is high, empty the queue + // Semantically, any enqueues happen before the flush. when (do_enq) { ram(enq_ptr.value) := io.enq.bits enq_ptr.inc() @@ -238,6 +244,11 @@ class Queue[T <: Data](val gen: T, when (do_enq =/= do_deq) { maybe_full := do_enq } + when(flush) { + enq_ptr.reset() + deq_ptr.reset() + maybe_full := false.B + } io.deq.valid := !empty io.enq.ready := !full @@ -265,6 +276,7 @@ class Queue[T <: Data](val gen: T, } val ptr_diff = enq_ptr.value - deq_ptr.value + if (isPow2(entries)) { io.count := Mux(maybe_full && ptr_match, entries.U, 0.U) | ptr_diff } else { @@ -296,7 +308,8 @@ object Queue entries: Int = 2, pipe: Boolean = false, flow: Boolean = false, - useSyncReadMem: Boolean = false): DecoupledIO[T] = { + useSyncReadMem: Boolean = false, + hasFlush: Boolean = false): DecoupledIO[T] = { if (entries == 0) { val deq = Wire(new DecoupledIO(chiselTypeOf(enq.bits))) deq.valid := enq.valid @@ -304,7 +317,7 @@ object Queue enq.ready := deq.ready deq } else { - val q = Module(new Queue(chiselTypeOf(enq.bits), entries, pipe, flow, useSyncReadMem)) + val q = Module(new Queue(chiselTypeOf(enq.bits), entries, pipe, flow, useSyncReadMem, hasFlush)) q.io.enq.valid := enq.valid // not using <> so that override is allowed q.io.enq.bits := enq.bits enq.ready := q.io.enq.ready |
