-
Notifications
You must be signed in to change notification settings - Fork 640
Add IrrevocableIO alternative to DecoupledIO #274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
e3cd236
Add IrrevocableIO subclass of DecoupledIO that promises not to change…
hcook e1ba700
Clarify valid semantics in comment
hcook 032e188
Un-sub-class IrrevocableIO from DecoupledIO, undo change to QueueIO, …
hcook 1c82796
Better comments and a default flow parameter in the Queue factory
hcook File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,23 +7,68 @@ package chisel3.util | |
|
|
||
| import chisel3._ | ||
|
|
||
| /** An I/O Bundle with simple handshaking using valid and ready signals for data 'bits'*/ | ||
| class DecoupledIO[+T <: Data](gen: T) extends Bundle | ||
| /** An I/O Bundle containing 'valid' and 'ready' signals that handshake | ||
| * the transfer of data stored in the 'bits' subfield. | ||
| * The base protocol implied by the directionality is that the consumer | ||
| * uses the flipped interface. Actual semantics of ready/valid are | ||
| * enforced via use of concrete subclasses. | ||
| */ | ||
| abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle | ||
| { | ||
| val ready = Bool(INPUT) | ||
| val valid = Bool(OUTPUT) | ||
| val bits = gen.cloneType.asOutput | ||
| def fire(dummy: Int = 0): Bool = ready && valid | ||
| override def cloneType: this.type = new DecoupledIO(gen).asInstanceOf[this.type] | ||
| } | ||
|
|
||
| /** Adds a ready-valid handshaking protocol to any interface. | ||
| * The standard used is that the consumer uses the flipped interface. | ||
| /** A concrete subclass of ReadyValidIO signalling that the user expects a | ||
| * "decoupled" interface: 'valid' indicates that the producer has | ||
| * put valid data in 'bits', and 'ready' indicates that the consumer is ready | ||
| * to accept the data this cycle. No requirements are placed on the signalling | ||
| * of ready or valid. | ||
| */ | ||
| object Decoupled { | ||
| class DecoupledIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) | ||
| { | ||
| override def cloneType: this.type = new DecoupledIO(gen).asInstanceOf[this.type] | ||
| } | ||
|
|
||
| /** This factory adds a decoupled handshaking protocol to a data bundle. */ | ||
| object Decoupled | ||
| { | ||
| /** Take any Data and wrap it in a DecoupledIO interface */ | ||
| def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) | ||
|
|
||
| /** Take an IrrevocableIO and cast it to a DecoupledIO. | ||
| * This cast is only safe to do in cases where the IrrevocableIO | ||
| * is being produced as an output. | ||
| */ | ||
| def apply[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = { | ||
| require(irr.bits.dir == OUTPUT, "Only safe to cast produced Irrevocable bits to Decoupled.") | ||
| val d = Wire(new DecoupledIO(irr.bits)) | ||
| d.bits := irr.bits | ||
| d.valid := irr.valid | ||
| irr.ready := d.ready | ||
| d | ||
| } | ||
| } | ||
|
|
||
| /** A concrete subclass of ReadyValidIO that promises to not change | ||
| * the value of 'bits' after a cycle where 'valid' is high and 'ready' is low. | ||
| * Additionally, once 'valid' is raised it will never be lowered until after | ||
| * 'ready' has also been raised. | ||
| */ | ||
| class IrrevocableIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) | ||
| { | ||
| override def cloneType: this.type = new IrrevocableIO(gen).asInstanceOf[this.type] | ||
| } | ||
|
|
||
| /** Factory adds an irrevocable handshaking protocol to a data bundle. */ | ||
| object Irrevocable | ||
| { | ||
| def apply[T <: Data](gen: T): IrrevocableIO[T] = new IrrevocableIO(gen) | ||
| } | ||
|
|
||
|
|
||
| /** An I/O bundle for enqueuing data with valid/ready handshaking | ||
| * Initialization must be handled, if necessary, by the parent circuit | ||
| */ | ||
|
|
@@ -103,7 +148,8 @@ class QueueIO[T <: Data](gen: T, entries: Int) extends Bundle | |
| * q.io.enq <> producer.io.out | ||
| * consumer.io.in <> q.io.deq }}} | ||
| */ | ||
| class Queue[T <: Data](gen: T, val entries: Int, | ||
| class Queue[T <: Data](gen: T, | ||
| val entries: Int, | ||
| pipe: Boolean = false, | ||
| flow: Boolean = false, | ||
| override_reset: Option[Bool] = None) | ||
|
|
@@ -164,22 +210,43 @@ extends Module(override_reset=override_reset) { | |
| } | ||
| } | ||
|
|
||
| /** Generic hardware queue. Required parameter entries controls | ||
| the depth of the queues. The width of the queue is determined | ||
| from the inputs. | ||
|
|
||
| Example usage: | ||
| {{{ val q = Queue(Decoupled(UInt()), 16) | ||
| q.io.enq <> producer.io.out | ||
| consumer.io.in <> q.io.deq }}} | ||
| /** Factory for a generic hardware queue. Required parameter 'entries' controls | ||
| * the depth of the queues. The width of the queue is determined | ||
| * from the input 'enq'. | ||
| * | ||
| * Example usage: | ||
| * {{{ consumer.io.in <> Queue(producer.io.out, 16) }}} | ||
| */ | ||
| object Queue | ||
| { | ||
| def apply[T <: Data](enq: DecoupledIO[T], entries: Int = 2, pipe: Boolean = false): DecoupledIO[T] = { | ||
| /** Create a queue and supply a DecoupledIO containing the product. */ | ||
| def apply[T <: Data]( | ||
| enq: ReadyValidIO[T], | ||
| entries: Int = 2, | ||
| pipe: Boolean = false, | ||
| flow: Boolean = false): DecoupledIO[T] = { | ||
| val q = Module(new Queue(enq.bits.cloneType, entries, pipe)) | ||
| 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 | ||
| TransitName(q.io.deq, q) | ||
| } | ||
|
|
||
| /** 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. | ||
| */ | ||
| def irrevocable[T <: Data]( | ||
| enq: ReadyValidIO[T], | ||
| entries: Int = 2, | ||
| pipe: Boolean = false, | ||
| flow: Boolean = false): IrrevocableIO[T] = { | ||
| val deq = apply(enq, entries, pipe) | ||
| val irr = Wire(new IrrevocableIO(deq.bits)) | ||
| irr.bits := deq.bits | ||
| irr.valid := deq.valid | ||
| deq.ready := irr.ready | ||
| irr | ||
| } | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While we're at it, could we have 'flow' added as another defaulted argument on the Queue.methods? |
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add scaladoc for the two apply methods? the new one should explain the use case and the invariant