Skip to content

[FIRRTL] Add lower-to-core lowering mode#10162

Draft
uenoku wants to merge 3 commits intollvm:mainfrom
uenoku:dev/hidetou/lower-to-core
Draft

[FIRRTL] Add lower-to-core lowering mode#10162
uenoku wants to merge 3 commits intollvm:mainfrom
uenoku:dev/hidetou/lower-to-core

Conversation

@uenoku
Copy link
Copy Markdown
Member

@uenoku uenoku commented Apr 9, 2026

This PR introduces an option (--lower-to-core) to force lowering to pure core dialects (generally verif/sim) by ignoring legacy lowering.

I think the unfortunate fact is that it's unrealistic to emit core dialects from LowerToHW without contaminating them with a bunch of ugly macro lowerings (e.g., STOP_COND, PRINTF_COND, PRINTF_COND_FRAGMENT, ASSERT_VERBOSE_COND, and __circt_lib_logging::FileDescriptor::get). These are highly specific to Chisel (or internal SiFive use cases), and this technical debt should not block circt-bmc or arcilator workflows.

The new option allows us to incrementally replace each lowering where possible. For instance, maybe printf could be handled if we had a way to replace STOP_COND with an external function call defined by the FIRRTL ABI, for which firtool could provide an interpretable default.

While I hope --lower-to-core eventually becomes the default, I'm a bit pessimistic about that transition.

As we discussed in ODM we might want to put core dialect representation to a different region, but I feel just providing option feels very pragmatic (and changes needed for LowerToHW look more manageable than what I originally imagined).

Let me know what you think! @fzi-hielscher @dobios @nanjo712

AI-assisted-by: GPT-5.4

@uenoku uenoku changed the title Dev/hidetou/lower to core [FIRRTL] Add lower-to-core lowering mode Apr 9, 2026
@uenoku uenoku force-pushed the dev/hidetou/lower-to-core branch from 8d65cae to 0bc4d0d Compare April 9, 2026 07:57
}

FailureOr<Value>
FIRRTLLowering::lowerSimFormatString(StringRef originalFormatString,
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to drop this function as I realized this is subsumed by #10153.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree there is overlap with the helper in #10153.
Given that #10153 currently depends on the larger #10146 stack and is harder to disentangle, I think keeping the simpler implementation local to #10162 is reasonable for now, especially since --lower-to-core is meant to be a pragmatic transitional path.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok that sounds good.

@nanjo712
Copy link
Copy Markdown
Contributor

nanjo712 commented Apr 9, 2026

Thanks, this makes a lot of sense to me.
I agree that --lower-to-core is a pragmatic way to unblock non-SV backends while we still have legacy macro lowerings in LowerToHW.
I see this as complementary to the cleanup direction: the option gives us an immediate escape hatch, while follow-up work can incrementally replace individual legacy lowerings with core-dialect representations where feasible.

Copy link
Copy Markdown
Member

@dobios dobios left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Just a little question about your choice of always lowering to a clockedassertlikes even when the clock is frivolous

auto edge = firrtlToVerifClockEdge(opEventControl);
auto opName = op->getName().stripDialect();
if (opName == "assert") {
verif::ClockedAssertOp::create(builder, predicate, edge, clock, enable,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are clocked assertions always the best way to go? I'm not quite sure they have full support in all of the backends yet?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be easier to just emit a regular assertion if the predicate is an i1. That would at least make it immediately usable for most cases.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or is there already a canonicalization that handles that?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think FIRRTL only has clocked assert. I'm not familiar with this area, what do you think the most reasonable lowering here? (or I can keep this blank so that you can take over).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm ok i guess this should be fine for now, I think it might be a good idea to push all of the backends to support this anyways

Copy link
Copy Markdown
Member

@dobios dobios left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a good start, we might want to revisit some of this later if it starts conflicting with the verification backends too much.

@dobios
Copy link
Copy Markdown
Member

dobios commented Apr 10, 2026

@uenoku

I think the unfortunate fact is that it's unrealistic to emit core dialects from LowerToHW without contaminating them with a bunch of ugly macro lowerings (e.g., STOP_COND, PRINTF_COND, PRINTF_COND_FRAGMENT, ASSERT_VERBOSE_COND, and __circt_lib_logging::FileDescriptor::get). These are highly specific to Chisel (or internal SiFive use cases), and this technical debt should not block circt-bmc or arcilator workflows.

Ideally those can simply be ignored in the verification backends, but it would be nice if there was an option to simply not emit them.

The new option allows us to incrementally replace each lowering where possible. For instance, maybe printf could be handled if we had a way to replace STOP_COND with an external function call defined by the FIRRTL ABI, for which firtool could provide an interpretable default.

While I hope --lower-to-core eventually becomes the default, I'm a bit pessimistic about that transition.

This will at least make going from chisel directly to the verification backends much cleaner, thanks!

As we discussed in ODM we might want to put core dialect representation to a different region, but I feel just providing option feels very pragmatic (and changes needed for LowerToHW look more manageable than what I originally imagined).

I prefer the idea of having an option define which type of lowering we want rather than just emitting both in separate regions as the latter will require some annoying edge case handling downstream which i don't think should be necessary.

Copy link
Copy Markdown
Contributor

@fabianschuiki fabianschuiki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an excellent idea! Having two lowering modes would give us a way to switch between status quo and the where we want to go, and then we can close the gap iteratively. LGTM!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants