diff options
| author | Jiuyang Liu | 2021-11-18 02:31:32 +0800 |
|---|---|---|
| committer | GitHub | 2021-11-17 18:31:32 +0000 |
| commit | 8f796df5693b560a086b95a24c5bd090064a639e (patch) | |
| tree | 0ab16d4075416ca5961ce32fcb58b13b331aef5a | |
| parent | 670c539110a599642d700323a34159be0f5abb12 (diff) | |
refactor Queue.hasFlush: Boolean to Queue.flush: Option[Bool]. (#2245)
* refactor Queue.hasFlush: Boolean to Queue.flush: Option[Bool].
Using factory Queue(..., hasFlush = true) won't take effects, since in the Queue.apply API, Queue Module is not exposed, thus even user defines hasFlush = true, there is no place for them to give the flush signal.
This commit fix this, refactor Queue.hasFlush: Boolean to Queue.flush: Option[Bool], makes user be able to pass the flush signal into Queue Module.
* use zip to connect.
* refactor docs.
Co-authored-by: Megan Wachs <megan@sifive.com>
| -rw-r--r-- | src/main/scala/chisel3/util/Decoupled.scala | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 2a098f4d..4b8b3eeb 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -249,7 +249,7 @@ class Queue[T <: Data](val gen: T, 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) + val flush = io.flush.getOrElse(false.B) // when flush is high, empty the queue // Semantically, any enqueues happen before the flush. @@ -307,20 +307,26 @@ class Queue[T <: Data](val gen: T, } } -/** Factory for a generic hardware queue. - * - * @param enq input (enqueue) interface to the queue, also determines width of queue elements - * @param entries depth (number of elements) of the queue - * - * @return output (dequeue) interface from the queue - * - * @example {{{ - * consumer.io.in <> Queue(producer.io.out, 16) - * }}} - */ +/** Factory for a generic hardware queue. */ object Queue { - /** Create a queue and supply a DecoupledIO containing the product. */ + /** Create a [[Queue]] and supply a [[DecoupledIO]] containing the product. + * + * @param enq input (enqueue) interface to the queue, also determines type of queue elements. + * @param entries depth (number of elements) of the queue + * @param pipe True if a single entry queue can run at full throughput (like a pipeline). The `ready` signals are + * combinationally coupled. + * @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 flush Optional [[Bool]] signal, if defined, the [[Queue.hasFlush]] will be true, and connect correspond + * signal to [[Queue]] instance. + * @return output (dequeue) interface from the queue. + * + * @example {{{ + * consumer.io.in <> Queue(producer.io.out, 16) + * }}} + */ @chiselName def apply[T <: Data]( enq: ReadyValidIO[T], @@ -328,7 +334,7 @@ object Queue pipe: Boolean = false, flow: Boolean = false, useSyncReadMem: Boolean = false, - hasFlush: Boolean = false): DecoupledIO[T] = { + flush: Option[Bool] = None): DecoupledIO[T] = { if (entries == 0) { val deq = Wire(new DecoupledIO(chiselTypeOf(enq.bits))) deq.valid := enq.valid @@ -336,7 +342,8 @@ object Queue enq.ready := deq.ready deq } else { - val q = Module(new Queue(chiselTypeOf(enq.bits), entries, pipe, flow, useSyncReadMem, hasFlush)) + val q = Module(new Queue(chiselTypeOf(enq.bits), entries, pipe, flow, useSyncReadMem, flush.isDefined)) + q.io.flush.zip(flush).foreach(f => f._1 := f._2) 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 @@ -344,10 +351,25 @@ object Queue } } - /** Create a queue and supply a IrrevocableIO containing the product. - * Casting from Decoupled is safe here because we know the Queue has - * Irrevocable semantics; we didn't want to change the return type of - * apply() for backwards compatibility reasons. + /** Create a queue and supply a [[IrrevocableIO]] containing the product. + * Casting from [[DecoupledIO]] is safe here because we know the [[Queue]] has + * Irrevocable semantics. + * we didn't want to change the return type of apply() for backwards compatibility reasons. + * + * @param enq [[DecoupledIO]] signal to enqueue. + * @param entries The max number of entries in the queue + * @param pipe True if a single entry queue can run at full throughput (like a pipeline). The ''ready'' signals are + * combinationally coupled. + * @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 flush Optional [[Bool]] signal, if defined, the [[Queue.hasFlush]] will be true, and connect correspond + * signal to [[Queue]] instance. + * @return a [[DecoupledIO]] signal which should connect to the dequeue signal. + * + * @example {{{ + * consumer.io.in <> Queue(producer.io.out, 16) + * }}} */ @chiselName def irrevocable[T <: Data]( @@ -355,8 +377,9 @@ object Queue entries: Int = 2, pipe: Boolean = false, flow: Boolean = false, - useSyncReadMem: Boolean = false): IrrevocableIO[T] = { - val deq = apply(enq, entries, pipe, flow, useSyncReadMem) + useSyncReadMem: Boolean = false, + flush: Option[Bool] = None): IrrevocableIO[T] = { + val deq = apply(enq, entries, pipe, flow, useSyncReadMem, flush) require(entries > 0, "Zero-entry queues don't guarantee Irrevocability") val irr = Wire(new IrrevocableIO(chiselTypeOf(deq.bits))) irr.bits := deq.bits |
