I’ve been taking a look at the
FIRRTL lowerings for
Handshake's ops that implement merging and branching (the
ConditionalBranchOp). Right now all of those lowerings make use of the
WhenOp (and appear to be the only use of the
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
WhenOps, 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
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.