-
Notifications
You must be signed in to change notification settings - Fork 413
Add circt-tblgen, generate FIRRTL intrinsics docs #9454
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
e0a3254 to
c8888f3
Compare
Add a `circt-tblgen` tool identical to how MLIR has this set up. This needs to be pulled in by the root cmake file to ensure that the interesting `CIRCT_TABLEGEN_EXE` and `CIRCT_TABLEGEN_TARGET` variables are visible to the rest of the project. Having a custom TableGen in CIRCT allows us to be more fancy about how we generate code from tables. As a first example, add a backend to generate the code to register lowerings for FIRRTL intrinsics, and a backend to generate Markdown documentation snippets from the same table. I have only migrated two intrinsics over into the table to not pollute the PR with a purely mechanical change. Once this lands we can follow up with a PR that moves all intrinsics into that table. This then enforces that every supported FIRRTL intrinsic has corresponding documentation. I'm sure we can find a lot more uses for circt-tblgen :-)
c8888f3 to
df04281
Compare
dtzSiFive
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really neat, thanks for putting this together!
I've left some feedback.
I have not carefully reviewed the CMake portion, and I recall it being quite .. involved, having previously poked at use in the MLIR-built-and-installed-standalone flow I use for packaging.
One possibly useful litmus test -- possibly after this PR -- is to see how well this can be used from a downstream project. Especially from an install (not just a build tree as often used).
Anyway when we move forward with this let's see if we can't be sure to follow-up promptly-ish (I'll help!) so we get everything moved over quickly (and don't have things mid-transition for too long). Not eagerly converting things, especially while under review, is a good call for now 👍 .
| // lowering code, as well as fragments for the dialect documentation. | ||
| class FIRRTLIntrinsic { | ||
| // The mnemonic for the intrinsic, e.g. "circt.sizeof". This should use the | ||
| // form with dots. A second mnemonic with only underscores will be generated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we standardized on the underscore format, actually, and that's what the user-facing documentation uses today. I'm not sure offhand if there's any utility in keeping the dot variant in today's flows, but I'd want to triple-check where that was ever used, to be honest.
I'm open to arguments the other way, but regardless of which format we decide on I don't think it makes much sense to actually support both other than as a transition detail / legacy support.
(right? WDYT?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concrete suggestion was to make the underscore version the primary format, but we can't produce the dot format easily from that (which may have underscores as well), so that might be something that "goes along with" removing supporting both.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good points! I've had a similar reaction: let's make the underscore the default -- and then I realized that the dot format needs to be the default because we can't get that from the underscore format. But since this is now generated, I think once we've migrated everything over and we have officially removed support for ".", we can just tweak the few lines here?
|
|
||
| | Argument | Type | Description | | ||
| | -------- | ---- | ------------------------------------------ | | ||
| | i | Any | value whose type's size is to be returned | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be super neat to auto-generate these tables! 🙃
Something like how arguments / results / parameters are defined for MLIR instructions, maybe? Just brainstorming.
That said, I don't know how well we could auto-generate (for example) the check/convert snippets for the majority of cases, from a programmatic / table description. A few likely will still make more sense done manually or at least via escape-hatch "just use this code as the check or convert part".
Maybe we could or otherwise could basically provide the same "interface" as currently given when adding an intrinsic re:what's needed to derive from one of the Conversion helpers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just moving this over verbatim is a great start, can't help but getting excited about where things might be able to go! 😁
It's valuable to not overdo things in that direction too hastily, probably, but curious what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be so cool to autogenerate! The snippets in the converter that handle the different flavors of arguments are a bit tricky though, as you say. Maybe we gradually increase how much of this we autogenerate over time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
| struct IntrinsicDef { | ||
| const Record *def; | ||
| StringRef mnemonic; | ||
| std::string altMnemonic; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SmallString's instead of std::string ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had that initially, and then I remember that there are on the order of 100 of these that get allocated, and SmallString was giving off that strong premature optimization smell 🤣 . I'm happy to switch this to SmallString though if you want 😁
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah, keep it.
I haven't looked at this closely enough 🙃 and let's go with your preference. Hence the question mark 😉 .
Thing I argue for most directly is avoiding a bunch of temporary std::string allocations on the way to constructing the final thing, which is only even a tiny bit relevant re:converter. And the fact that in practice it's unlikely these names will be very long.
I wonder how much the common sort of "SSO" gets us, anyway...
Just beating the good practices drum 😉 .
| mnemonic = def->getValueAsString("mnemonic"); | ||
| description = def->getValueAsOptionalString("description").value_or(""); | ||
|
|
||
| // Determine the alternative mnemonic by replacing any unsavory characters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"unsavory characters" 🤣 ❤️
Add a
circt-tblgentool identical to how MLIR has this set up. This needs to be pulled in by the root cmake file to ensure that the interestingCIRCT_TABLEGEN_EXEandCIRCT_TABLEGEN_TARGETvariables are visible to the rest of the project.Having a custom TableGen in CIRCT allows us to be more fancy about how we generate code from tables. As a first example, add a backend to generate the code to register lowerings for FIRRTL intrinsics, and a backend to generate Markdown documentation snippets from the same table.
I have only migrated two intrinsics over into the table to not pollute the PR with a purely mechanical change. Once this lands we can follow up with a PR that moves all intrinsics into that table. This then enforces that every supported FIRRTL intrinsic has corresponding documentation.
I'm sure we can find a lot more uses for circt-tblgen :-)