diff options
| author | Jack | 2022-01-12 04:27:19 +0000 |
|---|---|---|
| committer | Jack | 2022-01-12 04:27:19 +0000 |
| commit | 29df513e348cc809876893f650af8180f0190496 (patch) | |
| tree | 06daaea954b4e5af7113f06e4bdbb78b33515cb3 /src/main/scala/chisel3/util/Decoupled.scala | |
| parent | 5242ce90659decb9058ee75db56e5c188029fbf9 (diff) | |
| parent | 747d16311bdf185d2e98e452b14cb5d8ccca004c (diff) | |
Merge branch 'master' into 3.5-release
Diffstat (limited to 'src/main/scala/chisel3/util/Decoupled.scala')
| -rw-r--r-- | src/main/scala/chisel3/util/Decoupled.scala | 157 |
1 files changed, 87 insertions, 70 deletions
diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 4b8b3eeb..5c71a4ea 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -6,8 +6,8 @@ package chisel3.util import chisel3._ -import chisel3.experimental.{DataMirror, Direction, requireIsChiselType} -import chisel3.internal.naming._ // can't use chisel3_ version because of compile order +import chisel3.experimental.{requireIsChiselType, DataMirror, Direction} +import chisel3.internal.naming._ // can't use chisel3_ version because of compile order /** An I/O Bundle containing 'valid' and 'ready' signals that handshake * the transfer of data stored in the 'bits' subfield. @@ -18,40 +18,41 @@ import chisel3.internal.naming._ // can't use chisel3_ version because of compi * @param gen the type of data to be wrapped in Ready/Valid * @groupdesc Signals The actual hardware fields of the Bundle */ -abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle -{ +abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle { // Compatibility hack for rocket-chip private val genType = (DataMirror.internal.isSynthesizable(gen), chisel3.internal.Builder.currentModule) match { - case (true, Some(module: Module)) - if !module.compileOptions.declaredTypeMustBeUnbound => chiselTypeOf(gen) + case (true, Some(module: Module)) if !module.compileOptions.declaredTypeMustBeUnbound => chiselTypeOf(gen) case _ => gen } -/** Indicates that the consumer is ready to accept the data this cycle - * @group Signals - */ + /** Indicates that the consumer is ready to accept the data this cycle + * @group Signals + */ val ready = Input(Bool()) - -/** Indicates that the producer has put valid data in 'bits' - * @group Signals - */ + + /** Indicates that the producer has put valid data in 'bits' + * @group Signals + */ val valid = Output(Bool()) - -/** The data to be transferred when ready and valid are asserted at the same cycle - * @group Signals - */ - val bits = Output(genType) + + /** The data to be transferred when ready and valid are asserted at the same cycle + * @group Signals + */ + val bits = Output(genType) } object ReadyValidIO { - implicit class AddMethodsToReadyValid[T<:Data](target: ReadyValidIO[T]) { + implicit class AddMethodsToReadyValid[T <: Data](target: ReadyValidIO[T]) { /** Indicates if IO is both ready and valid - */ + */ def fire: Bool = target.ready && target.valid - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def fire(dummy: Int = 0): Bool = fire /** Push dat onto the output bits of this interface to let the consumer know it has happened. @@ -99,8 +100,8 @@ object ReadyValidIO { class DecoupledIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) /** This factory adds a decoupled handshaking protocol to a data bundle. */ -object Decoupled -{ +object Decoupled { + /** Wraps some Data with a DecoupledIO interface. */ def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) @@ -110,6 +111,7 @@ object Decoupled // Both of these methods return DecoupledIO parameterized by the most generic type: Data /** Returns a [[DecoupledIO]] inteface with no payload */ def apply(): DecoupledIO[Data] = apply(new EmptyBundle) + /** Returns a [[DecoupledIO]] inteface with no payload */ def empty: DecoupledIO[Data] = Decoupled() @@ -119,7 +121,10 @@ object Decoupled */ @chiselName def apply[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = { - require(DataMirror.directionOf(irr.bits) == Direction.Output, "Only safe to cast produced Irrevocable bits to Decoupled.") + require( + DataMirror.directionOf(irr.bits) == Direction.Output, + "Only safe to cast produced Irrevocable bits to Decoupled." + ) val d = Wire(new DecoupledIO(chiselTypeOf(irr.bits))) d.bits := irr.bits d.valid := irr.valid @@ -138,8 +143,7 @@ object Decoupled class IrrevocableIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) /** Factory adds an irrevocable handshaking protocol to a data bundle. */ -object Irrevocable -{ +object Irrevocable { def apply[T <: Data](gen: T): IrrevocableIO[T] = new IrrevocableIO(gen) /** Upconverts a DecoupledIO input to an IrrevocableIO, allowing an IrrevocableIO to be used @@ -148,7 +152,10 @@ object Irrevocable * @note unsafe (and will error) on the consumer (output) side of an DecoupledIO */ def apply[T <: Data](dec: DecoupledIO[T]): IrrevocableIO[T] = { - require(DataMirror.directionOf(dec.bits) == Direction.Input, "Only safe to cast consumed Decoupled bits to Irrevocable.") + require( + DataMirror.directionOf(dec.bits) == Direction.Input, + "Only safe to cast consumed Decoupled bits to Irrevocable." + ) val i = Wire(new IrrevocableIO(chiselTypeOf(dec.bits))) dec.bits := i.bits dec.valid := i.valid @@ -161,13 +168,14 @@ object Irrevocable * @param gen The type of data to enqueue */ object EnqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = Decoupled(gen) + def apply[T <: Data](gen: T): DecoupledIO[T] = Decoupled(gen) } + /** Consumer - drives (outputs) ready, inputs valid and bits. * @param gen The type of data to dequeue */ object DeqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(Decoupled(gen)) + def apply[T <: Data](gen: T): DecoupledIO[T] = Flipped(Decoupled(gen)) } /** An I/O Bundle for Queues @@ -176,28 +184,34 @@ object DeqIO { * @param hasFlush A boolean for whether the generated Queue is flushable * @groupdesc Signals The hardware fields of the 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. +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, * but internally, the queue implementation itself sits on the other side * of the interface so uses the flipped instance. */ - /** I/O to enqueue data (client is producer, and Queue object is consumer), is [[Chisel.DecoupledIO]] flipped. + /** I/O to enqueue data (client is producer, and Queue object is consumer), is [[Chisel.DecoupledIO]] flipped. * @group Signals */ val enq = Flipped(EnqIO(gen)) + /** I/O to dequeue data (client is consumer and Queue object is producer), is [[Chisel.DecoupledIO]] * @group Signals */ val deq = Flipped(DeqIO(gen)) - /** The current amount of data in the queue + + /** The current amount of data in the queue * @group Signals */ 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) * @group Signals - */ + */ val flush = if (hasFlush) Some(Input(Bool())) else None } @@ -218,13 +232,15 @@ class QueueIO[T <: Data](private val gen: T, val entries: Int, val hasFlush: Boo * }}} */ @chiselName -class Queue[T <: Data](val gen: T, - val entries: Int, - val pipe: Boolean = false, - val flow: Boolean = false, - val useSyncReadMem: Boolean = false, - val hasFlush: Boolean = false) - (implicit compileOptions: chisel3.CompileOptions) +class Queue[T <: Data]( + val gen: T, + val entries: Int, + val pipe: Boolean = false, + val flow: 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") require(entries != 0, "Use companion object Queue.apply for zero entries") @@ -253,21 +269,21 @@ class Queue[T <: Data](val gen: T, // when flush is high, empty the queue // Semantically, any enqueues happen before the flush. - when (do_enq) { + when(do_enq) { ram(enq_ptr.value) := io.enq.bits enq_ptr.inc() } - when (do_deq) { + when(do_deq) { deq_ptr.inc() } - when (do_enq =/= do_deq) { + 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 @@ -276,22 +292,21 @@ class Queue[T <: Data](val gen: T, val deq_ptr_next = Mux(deq_ptr.value === (entries.U - 1.U), 0.U, deq_ptr.value + 1.U) val r_addr = WireDefault(Mux(do_deq, deq_ptr_next, deq_ptr.value)) io.deq.bits := ram.read(r_addr) - } - else { + } else { io.deq.bits := ram(deq_ptr.value) } if (flow) { - when (io.enq.valid) { io.deq.valid := true.B } - when (empty) { + when(io.enq.valid) { io.deq.valid := true.B } + when(empty) { io.deq.bits := io.enq.bits do_deq := false.B - when (io.deq.ready) { do_enq := false.B } + when(io.deq.ready) { do_enq := false.B } } } if (pipe) { - when (io.deq.ready) { io.enq.ready := true.B } + when(io.deq.ready) { io.enq.ready := true.B } } val ptr_diff = enq_ptr.value - deq_ptr.value @@ -299,17 +314,17 @@ class Queue[T <: Data](val gen: T, if (isPow2(entries)) { io.count := Mux(maybe_full && ptr_match, entries.U, 0.U) | ptr_diff } else { - io.count := Mux(ptr_match, - Mux(maybe_full, - entries.asUInt, 0.U), - Mux(deq_ptr.value > enq_ptr.value, - entries.asUInt + ptr_diff, ptr_diff)) + io.count := Mux( + ptr_match, + Mux(maybe_full, entries.asUInt, 0.U), + Mux(deq_ptr.value > enq_ptr.value, entries.asUInt + ptr_diff, ptr_diff) + ) } } /** Factory for a generic hardware queue. */ -object Queue -{ +object Queue { + /** Create a [[Queue]] and supply a [[DecoupledIO]] containing the product. * * @param enq input (enqueue) interface to the queue, also determines type of queue elements. @@ -329,12 +344,13 @@ object Queue */ @chiselName def apply[T <: Data]( - enq: ReadyValidIO[T], - entries: Int = 2, - pipe: Boolean = false, - flow: Boolean = false, - useSyncReadMem: Boolean = false, - flush: Option[Bool] = None): DecoupledIO[T] = { + enq: ReadyValidIO[T], + entries: Int = 2, + pipe: Boolean = false, + flow: Boolean = false, + useSyncReadMem: Boolean = false, + flush: Option[Bool] = None + ): DecoupledIO[T] = { if (entries == 0) { val deq = Wire(new DecoupledIO(chiselTypeOf(enq.bits))) deq.valid := enq.valid @@ -373,12 +389,13 @@ object Queue */ @chiselName def irrevocable[T <: Data]( - enq: ReadyValidIO[T], - entries: Int = 2, - pipe: Boolean = false, - flow: Boolean = false, - useSyncReadMem: Boolean = false, - flush: Option[Bool] = None): IrrevocableIO[T] = { + enq: ReadyValidIO[T], + entries: Int = 2, + pipe: Boolean = false, + flow: Boolean = false, + 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))) |
