I am not sure, but I’m concerned that this won’t compose well. This wasn’t an accident. Verilog supports multiple connects to a wire both because of control flow (as you mention) but also because of Z values, where you can have:
x <= thing1
x <= thing2
with the assumption that one or the other will be z at any given time. This is semantically equivaelnt to:
x <= rtl.merge(thing1, thing2)
for us, where rtl.merge is the SSA dataflow version of connections.
First observation is that rtl.wire doesn’t really make sense for the RTL dialect, it is more of an SV thing, because its only needed purpose is to generate named wires in the output verilog. For all other things you can use rtl.merge (or the value directly) because the RTL dialect allows cycles in the graph.
Second observation is that we don’t have a model for what wires we want to persist (as mentioned on this patch) and that will be really necessary at some point. This is a human issue, not a dataflow optimization issue, so pushing this into SV instead of RTL makes sense.
If you agree it needs to be in the SV dialect to support hte need of humans, then this gets to the question of “should we do this”? It is trivially that any multiconnect could be implemented in terms of a single connect and merge, but I see two problems:
- This won’t generate as nice of Verilog, and won’t track location info in the same way (where each connect will have its own loc)
- This doesn’t actually make dataflow analysis any easier.
TLDR, I think the model we need here is:
- eliminate as many wires as we can that are not important for humans (e.g. the _T wires which get an empty name in FIRParser),
- retain the wires at the SV level that are left and use them as optimization blocks (because, e.g. a verification engineer wants to be able to probe them in the ultimate verilog etc)
- Synthesis or other tools would lower them harder in an explicit pass (not a canonicalization) to rtl.merges or other things that make synthesis convenient when they aren’t burdened with generating verilog.