calyx
calyx copied to clipboard
Calyx Standard Library Revamp
Summarizing discussion from our meeting today, we were trying to figure out what the right way to develop and integrate the Calyx standard library is. Specifically, we need to start caring about long-term stability and integration with CIRCT as top-level concerns for the library.
To summarize:
compile.futilis the set of primitives needed to compile Calyx programs. They are long-term stable and ship with the compiler source.core.futilcontains a mishmash of unsigned arithmetic, logical operations, andstd_memmath.futilcontainssqrtandpowimplementations which is kind of weirdbinary_operators.futilcontains signed arithmetic operators and sequential primitives like multipliers and dividerstcam.futilcontains the implementation for a TCAM which, again, is kind of weirdunsynthesizable.futilcontains unsynthesizable primitives that are useful for testingmemories.futilcontains sequential memories which are the long-term default memories we want to support
Proposed Changes
Here is a couple of proposed changes for the primitives library:
- Move the
std_memprimitives out ofcore.futiland intounsynthesizable.futil(#1261) - Merge the signed and unsigned arithmetic primitives and separate them into
comb.futilandsequential.futilinstead.- Rename the
*_pipeprimitives to not have the suffix since they are not pipelined - Rename the
*_fpprimitives to use the suffix_fixedinstead sincefpdenotes floating-point
- Rename the
- Move the mishmash files likes
tcam.futilandmath.futilinto another folder to denote that they are not considered for first-class support. Long-term, we want to replacemath.futilwith @bcarlet's numerics generator library
These changes will likely break code from all our frontends and so we need to coordinate with the Dahlia stuff and CIRCT before merging. Once done, we should do a new major release of the compiler
While we're considering breaking changes to the standard primitives, I'll also throw #497 in for consideration (as a potential breaking change to std_slice, specifically the change described here). I find myself needing a more general slice primitive fairly frequently, and I feel like the current version is oddly restrictive.
Absolutely! Do you want to take a shot at implementing a version that had both a start index and an end index? @andrewb1999 do you know if this matches the semantics of the CIRCT slice primitive?
Just wanted to flag a little weirdness in the fixed point prims. There are exactly three comparison ops
- gt
- sgt
- slt
There's no equality op (presumably since the std_eq works if we assume both fixed point numbers have the same fixed point, which is the operating assumption for all the fixed prims). It does seem a bit weird that we have a signed less than but no less than op (which of course can be realized with gt), probably we should either commit to a very minimal set of ops (removing slt) or we should make the full suite of standard comparisons for fixed point numbers if they're something we intend to provide as stable
Follow up, why does std_seq exist for signed bitnums, seems like that would be equivalent to the standard unsigned equality since we mandate the inputs be of the same width anyway?
@EclecticGriffin Agreed! This is weird. There should be exactly one equality and it should handle all these different formats. Also, yeah, each unsigned thing should have a signed counterpart. I'm not too worried about keeping it minimal so maybe we can add all the signed counterparts and remove the useless eq ones? Wanna take a shot at it?
Awesome! This is very much a good plan.
Just to iterate (i.e., bike-shed) on the details, here are a few assorted suggestions:
- Re.
std_mem: Instead of putting this inunsynthesizable.futil, maybe these should get their own file. We'd probably want to give this a new name, and the filename would match—something likecomb_mem? That name is silly because of course memories are never actually combinational; these just admit "combinational reads."tiny_mem?unrealistic_mem? (I don't think these things are totally useless, and they're not strictly speaking unsynthesizable—they should just not be most people's default choice.) - I like the idea of having a (directory) distinction between the stuff we want to keep stable—which could roughly be approximated as "everything that CIRCT compilation requires"—and everything else. In the future, it would be nice if "everything else" were moved out of the Calyx distribution and were in separate modules, but that is obviously a problem for another day. IMO the stable category should be as small as we can possibly make it; when in doubt, stuff goes in the "extra" category. (That probably includes what is currently called
std_mem_*, for example?) - Seems like all floating-point stuff should be in the "extra" category? Not sure.
they're not strictly speaking unsynthesizable
I think combinational multipliers are also not technically unsynthesizable but maybe a different point here is that unsynthesizable is a little strong; these modules are fine if you want to do modeling maybe?
On the other hand, @paili0628 is currently working on dual ported memories as well which will go into their own file. Long term maybe we just want all the memories in one place?
moved out of the Calyx distribution and were in separate modules, but that is obviously a problem for another day.
Right! This can be a part of the modules discussion. We almost want a calyx-extras package that ships all of these extra modules and generators that @anshumanmohan has been building up.