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:
- ports can be inout.
- such ports can be “used” and defined (with an rtl.connect)
- wires and other inout ports can be passed to instances as inout values.
As such, inouts and inputs are structurally different, 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:
- introduce a new
rtl.wireto always produce an
rtl.connectwould require its destination to be an
rtl.inout<T>and its source to be a
rtl.moduleports can already be anything, so
rtl.inout<T>values are allowed as ports without change.
- 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
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.