Support for floating/fixed/etc. types

In a recent review, it came up that we only support integer and index types in Handshake: https://github.com/llvm/circt/blob/main/lib/Conversion/HandshakeToFIRRTL/HandshakeToFIRRTL.cpp#L36. Similarly, FIRRTL does not support the fixed type defined by the FIRRTL spec: https://circt.llvm.org/docs/RationaleFIRRTL/#status.

I am curious if anyone has plans for supporting floating/fixed/etc. types at these levels. Has this been brought up before? I may be missing some of the background.

I’ve run up against this once already, so I’d like to get the ball rolling (or catch up) on this discussion. The main use case I’m looking at is coming from the higher levels into the Linalg dialect, where all the named ops are defined in terms of f32. You cannot invoke linalg.matmul unless the tensors or memrefs are floating points. This is just one example, and I think there will be more math-heavy use cases that want this.

I would like these sorts of programs to be supported by CIRCT, and I’m happy to participate in the design and implementation of this feature.

Parameterized float/fixed were originally going to be “high-level” ESI types, but they’re not appropriate for ESI in a CIRCT context. (I’m still planning on adding variable-length data types (lists) to ESI.) I think there’s a place for parameterized fixed/float types and operations on them in “circt::math” dialect.

I’m not aware of anyone interested in adding these to the FIRRTL dialect, at this time. Isn’t lowering of FP operations a complicated concept with lots of tradeoffs?

-Chris

Yes. I’m imagining a bunch of different lowerings depending on your design specs and/or target device. Perhaps start with just a module instance of an externmodule which is hand-coded SystemVerilog and can be selected at build time.

Either way, I think there’s value in standardizing these operations’ interfaces and allowing many implementations.

Agreed that this is complex and full of tradeoffs. That’s why I wanted to test the water now, before there are any deadlines. There’s no pressure for this support right now (on my end at least), so I’m hoping we can carve out a plan we are comfortable with. I will need to do something about this in my work to compile ML/scienctific programs, but if it would be easier to wait until I have a concrete problem to solve, I am happy to table this discussion for now.

I think both of John’s suggestions make sense. Defining these types and operations on them in some higher level circt::math dialect would be a nice way to start experimenting. Having the lowerings just select handcoded System Verilog modules seems like a nice way to unlock progress without having to build out too much support.

(By the way, this notion of selecting handcoded System Verilog has already come up in the ESI pipeline lowering, and I expect it to come up again. Maybe we can build some standard utilities to enable this across dialects.)

I would prefer that this be the exception (for cases where designers really want to fine tune the implementation) but I do expect it to happen. Using external SystemVerilog modules has the disadvantage of being opaque to CIRCT so it can’t be transformed or analyzed to – say – LLHD for fast simulator creation. I would suggest that we have default implementations in MLIR and then provide the option to replace that with hand-optimized SystemVerilog if we’re generating SystemVerilog. This could get sticky (since there are tunings which change the latency characteristics of the implementation) so we’d have to think it through. Could be in interesting and valuable feature in the long term though.

I did the ESI primitive since the functionality just wasn’t there to do it in the RTL or SV dialect. It was also a PITA to express the operations in C++, so wasn’t worth the effort for code which was 99% boilerplate. Is there a way to incorporate an MLIR assembly “template” into a transformation? Is this what the PDL dialect is going to do?

Yeah, agreed. The SV dialect already allows you to drop in textual verilog, but such an approach has all the same advantages and problems as inline asm does in C. Tools can’t analyze it etc. This is good for hacking and bringing things up quickly but isn’t a great long term play.