Skip to content
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

FixChisel3: Add some commentary to scaladoc #2339

Merged
merged 11 commits into from
May 17, 2020
42 changes: 37 additions & 5 deletions src/main/scala/util/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -234,23 +234,55 @@ package object util {
map.view.map({ case (k, vs) => k -> vs.toList }).toList
}

/** provides operators useful for working with bidirectional [[Bundle]]s
*
* In terms of [[Flipped]] with a producer 'p' and 'consumer' c:
* c :<= p // means drive all unflipped fields of 'c' from 'p' (e.g.: c.valid := p.valid)
* c :=> p // means drive all flipped fields of 'p' from 'c' (e.g.: `p.ready := c.ready`)
* c :<> p // do both of the above
* p :<> c // do both of the above, but you'll probably get a Flow error later.
*
* This utility class is needed because in [[chisel3]]:
* c := p // only works if there are no directions on fields.
* c <> p // only works if one of those is an [[IO]] (not a [[Wire]]).
*
* Compared with [[chisel3]] operators:
* c <> p is an 'actual-direction'-inferred 'c :<> p' or 'p :<> c'
* c := p is equivalent to 'c :<= p' + 'p :=> c'. In other words, drive ALL fields of 'c' from 'p' regardless of their direction.
*
* Contrast this with 'c :<> p' which will connect a ready-valid producer
* 'p' to a consumer 'c'.
* If you flip this to 'p :<> c', it works the way you would expect (flipping the role of producer/consumer).
* This is how Chisel._ (compatability mode) and firrtl work.
* Some find that ':<>' has superior readability (even if the direction can be inferred from an IO),
* because it clearly states the intended producer/consumer relationship.
* You will get an appropriate error if you connected it the wrong way
* (usually because you got the IO direction wrong) instead of silently succeeding.
*
* What if you want to connect all of the signals (e.g. ready/valid/bits)
* from producer 'p' to a monitor 'm'?
* For example in order to tap the connection to monitor traffic on an existing connection.
* In that case you can do 'm :<= p' and 'p :=> m'.
*/
implicit class EnhancedChisel3Assign[T <: Data](val x: T) extends AnyVal {
// Assign all output fields of x from y; note that the actual direction of x is irrelevant
/** Assign all output fields of x from y; note that the actual direction of x is irrelevant */
def :<= (y: T): Unit = FixChisel3.assignL(x, y)
// Assign all input fields of y from x; note that the actual direction of y is irrelevant
/** Assign all input fields of y from x; note that the actual direction of y is irrelevant */
def :=> (y: T): Unit = FixChisel3.assignR(x, y)
// Wire-friendly bulk connect
/** Bulk connect which will work between two [[Wire]]s (in addition to between [[IO]]s) */
def :<> (y: T): Unit = {
FixChisel3.assignL(x, y)
FixChisel3.assignR(x, y)
}
// x <> y is an 'actual-direction'-inferred 'x :<> y' or 'y :<> x'
// x := y is equivalent to 'x :<= y' + 'y :=> x'


// Versions of the operators that use the type from the RHS
// y :<=: x -> x.:<=:(y) -> y :<= x -> FixChisel3.assignL(y, x)
/** version of the :<= operator that uses the type from the RHS */
def :<=: (y: T): Unit = { FixChisel3.assignL(y, x) }
/** version of the :>= operator that uses the type from the RHS */
mwachs5 marked this conversation as resolved.
Show resolved Hide resolved
def :>=: (y: T): Unit = { FixChisel3.assignR(y, x) }
/** version of the :<> operator that uses the type from the RHS */
def :<>: (y: T): Unit = {
FixChisel3.assignL(y, x)
FixChisel3.assignR(y, x)
Expand Down