chipsalliance / chipsalliance/chisel
Clarifying Directionality in Chisel Types
- Dominant language
- Scala
- Stars
- 4.8k
- Forks
- 658
- Avg merge
- 18h 59m
- Merged PRs (30d)
- 14
Description
**Type of issue**: Feature Request
**Is your feature request related to a problem? Please describe.**
## Background: `Chisel._` vs `chisel3._` directionality
In `Chisel._`, `IO` has an implicit output direction, and `Flipped` is used for two things:
1) Define relative direction of a field with respect to its parent bundle
2) To change the implicit output to an implicit input of IO
```scala
val io = IO(new Bundle { // implicit output
val x = Flipped(UInt()) // x is flipped relative to bundle, so it is an input
val y = UInt() // y is aligned relative to bundle, so it is an output
})
```
You can declare an input port using the (2) kind of Flipped:
```scala
val io = IO(Flipped(new Bundle { // implicit input
val x = Flipped(UInt()) // x is flipped relative to bundle, so it is an output
val y = UInt() // y is aligned relative to bundle, so it is an input
}))
```
In `chisel3`, `IO` does not have an implicit direction, but `Input` and `Output` are specified on types, which coerce all subfields of the type to the same direction. `Flipped` inverts the absolute direction so `Input -> Output` and `Output -> Input`.
```scala
val io = IO(new Bundle { // no implicit direction
val x = Input(UInt()) // x is an input
val y = Output(UInt()) // y is an output
}))
```
You can switch directions with `Flipped`:
```scala
val io = IO(Flipped(new Bundle { // Swap all absolute directions
val x = Input(UInt()) // x is flipped so it is an output
val y = Output(UInt()) // y is flipped so it is an input
})))
```
**Describe the solution you'd like**
## Unifying directionality with new primitives
Both mechanisms of describing field directions can be unified with the following (conceptual) primitives:
- `Flipped`: a field's relative direction is reversed with respect to its parent bundle
- `Aligned`: a field's relative direction is the same with respect to its parent bundle (is implicit)
- `Outgoing`: an IO whose implicit direction is output
- `Incoming`: an IO whose implicit direction is input
- `stripFlipsOf`: a type-generator that aligns all subfields, recursively
- `reverseFlipsOf`: a type-generator that flips all subfields, recursively
Expressing Chisel._ semantics:
- `IO(new Bundle))` becomes `Outgoing(new Bundle)`
- `IO(Flipped(new Bundle))` becomes `Incoming(new Bundle)`; note that `Outgoing(reverseFlipsOf(new Bundle))` is the same, but I think it makes sense to have `Incoming` as well.
- `new Bundle { val x = UInt() }` is `new Bundle { val x = Aligned(UInt()) }`, or unchanged as `Aligned` is implicit
- `new Bundle { val x = Flipped(UInt()) }` is unchanged
Expressing chisel3._ semantics:
- `IO(new Bundle))` becomes `Outgoing(new Bundle)`
- `IO(Flipped(new Bundle))` becomes `Incoming(new Bundle)`
- `new Bundle { val x = Output(UInt()) }` is `new Bundle { val x = Aligned(stripFlipsOf(UInt())) }`
- `new Bundle { val x = Input(UInt()) }` is `new Bundle { val x = Flipped(stripFlipsOf(UInt())) }`
**Describe alternatives you've considered**
keeping things the same as they are.
**Additional context**
**What is the use case for implementing this feature?**
Being able to unify and improve LegacyChisel vs chisel3 connection semantics to overall simplify the code base.
Contributor guide
Assessment
This issue has not been assessed yet.