chipsalliance / chipsalliance/chisel

Clarifying Directionality in Chisel Types

Open
#2,643 5 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.