I’ve been taking a look at the FIRRTL
lowerings for Handshake
’s ops that implement merging and branching (the MergeLikeOpInterface
ops MuxOp
, MergeOp
, ControlMergeOp
, and ConditionalBranchOp
). Right now all of those lowerings make use of the FIRRTL
WhenOp
(and appear to be the only use of the FIRRTL
WhenOp
).
In a previous discussion, Schuyler pointed out that these mid-level FIRRTL
ops are fairly complex.
Right now, there isn’t much support for these ops beyond creating them. They can’t be lowered to other dialects or printed with EmitVerilog.cpp
. Transformation(s) can be added to flesh out support for WhenOp
s, but there might be an opportunity here to improve the Handshake
lowering for the long term.
Instead of relying on the mid-level semantics of FIRRTL
, these ops could be lowered into a more explicit implementation at a lower level. I’m imagining using low-level FIRRTL
constructs that have analogues in the RTL
and LLHD
dialects. Essentially, combinational logic and registers.
This would allow us to define exactly the circuit we want to generate for these ops in a way that is less coupled to FIRRTL
’s semantics. It can be tricky to get the handshaking semantics right (i.e. waiting for inputs, not introducing combinational cycles, etc.). To me, this is actually an argument in favor of making the lowerings of these ops more explicit.
There are examples of how to implement these kinds of ops in hardware:
- the elastic components in Dynamatic, like Mux
- sections 3.3 and 3.4 here have nice visualizations and explanation for Mux, DeMux, and ControlMerge (and mention a Merge that is simpler than ControlMerge)
- certainly more… anyone have other references?
Is there interest in moving away from WhenOp
in these lowerings? If so, I’d be interested in continuing the discussion and working on the implementation.