[RTL] Improved modeling for `inout`

We’ve had a lot of discussions about how best to model inout ports in the RTL/SV level. @stephenneuendorffer has expressed discomfort about having inout at that level (preferring strict in/outs and normal logic at this level). Our current situation is that we have support for inout as an rtl.inout attribute on input arguments. It doesn’t carry semantics, but can get propagated down into verilog (where it also doesn’t have strong semantics).

I think we should change this to box things in a bit more. For the existing things in the RTL level, inout really should only be used for a few things:

  1. ports can be inout.
  2. such ports can be “used” and defined (with an rtl.connect)
  3. wires and other inout ports can be passed to instances as inout values.

As such, inouts and inputs are structurally different, and rtl.connect and rtl.wire are also special (and probably make Stephen uncomfortable :-).

I think we can handle this in a clean way: let’s make the following changes:

  1. introduce a new rtl.inout<T> type.
  2. constrain rtl.wire to always produce an rtl.inout<T> value
  3. rtl.connect would require its destination to be an rtl.inout<T> and its source to be a T.
  4. rtl.module ports can already be anything, so rtl.inout<T> values are allowed as ports without change.
  5. We need to allow uses of inout values, so introduce an rtl.useinout (better name preferred) which takes an rtl.inout<T> and returns a T.

This cleanly puts the weird inout behavior in a place that is cordoned off and doesn’t intersect with normal logic.

Does this make sense to others? If so, I can probably start work on it in the next week or two.


I like this approach!

An inout box type to box things in? I see what you did there.

haha. :roll_eyes:


This seems reasonable, but is probably pretty similar from a functional perspective. I think that it probably makes it easier to get the correctness checks as part of the type mechanism, rather than relying on verification checks. It also emphasizes that uses of inout values are ‘different’. I could also see a canonicalization-style transformation that cuts a design along rtl.useinout operations, perhaps.