FIRRTL aggregate types discussion

I have been taking a look at this hypothetical example from the SV interfaces PR as a lowering target for aggregate types in FIRRTL. So far I’ve pulled together enough to transform some IR like this:

firrtl.circuit "dataflow_example" {
  firrtl.module @dataflow_example(%in: !firrtl.bundle<valid: uint<1>, ready: flip<uint<1>>, data: uint<64>>,
                                  %out: !firrtl.bundle<valid: flip<uint<1>>, ready: uint<1>, data: flip<uint<64>>>) {
  }
}

Into this:

firrtl.circuit "dataflow_example" {
  sv.interface @i2086446170726900693  {
    sv.interface.signal @valid : ui1
    sv.interface.signal @ready : ui1
    sv.interface.signal @data : ui64
    sv.interface.modport @mp16117715832878755040  ("input" @valid, "output" @ready, "input" @data)
    sv.interface.modport @mp12676913513676193433  ("output" @valid, "input" @ready, "output" @data)
  }
  firrtl.module @dataflow_example(%in: !sv.interface_modport<i2086446170726900693, mp16117715832878755040>,
                                  %out: !sv.interface_modport<i2086446170726900693, mp12676913513676193433>) {
  }
}

I can clean up my branch and push the proof of concept up to GitHub, but I’m curious if anyone has feedback on the utility of having such a pass. It is intended to lower bundles generated by HandshakeToFIRRTL towards something that EmitVeilog can process.

The new sv.interface_modport type gets inserted for every port of bundle type, and then it is up to the rest of the FIRRTL module to determine the semantics. I’ve been thinking about this hypothetically, but this is the first pass where I’ve put to use the new SV operations and type.

I’m curious if anyone has feedback on the above, and I’m also thinking about what directions this IR can go from here.

First and foremost, I’m trying to lower a FIRRTL circuit into something I can emit as System Verilog. Within EmitVerilog, it looks like we will need to add support for the new SV operations and type, and then thread through correct handling in some FIRRTL operations (instance, subfield, connect, maybe more). This is what I’m exploring now–if we can get from the above IR to correct, readable System Verilog.

I’m also looking into the new LLHD pass to lower from FIRRTL, and I’m seeing a need for “something” that can represent the aggregate types. I’m not as familiar with the LLHD dialect, so I’m not sure if the additions to the SV dialect and this lowering are useful to LLHD or not. It may make sense for LLHD to have it’s own representation here, but perhaps it can share something with the SV dialect.

I think similar questions come up in the lowering from FIRRTL to the RTL dialect as well. Do aggregate types have a place in the RTL dialect, or should they be lowered first? Should the RTL dialect depend on the SV dialect type system as a way to support aggregate types?

One overarching question I’m wondering at this point is whether people see utility in having the new operations and type in the SV dialect? It seems like that is the designated place for things that closely model System Verilog at the AST level, but we haven’t actually put any types into an SV type system. Does it make sense to start here?