Skip to content
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

[LTL to Core] Add lowering for AssertProperty operations #6974

Merged
merged 5 commits into from
May 2, 2024

Conversation

dobios
Copy link
Member

@dobios dobios commented Apr 30, 2024

In order to support the btor2 emission in Chisel, we need to have a good way to encode property assertions, as this should hopefully at some point be the default for formal verification.

This PR is a factored out version of #6649 that introduces a lowering pass for ltl and verif operations that are generated by the use of AssertProperty in Chisel, and encodes them using operations from the core dialects. This would allow for this assertion type to be used for Bounded Model Checking and is a first step for supported more SVA constructs in the formal backend.

Copy link
Member

@uenoku uenoku left a comment

Choose a reason for hiding this comment

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

Thank you for working on this! Looks promising! A few highlevel comments:

  1. I'm slightly nervous about having two lowering paths for hasBeenReset op in LTLToCore and VerifToSV. It is possible to unify them? I'm not sure the current two implementations are exactly same behavior in verilog though(LTLToCore lowers a reset value to power-on reset whereas LTLToVerif lowers it to initial statement).
  2. I think SV doesn't belong to core dialects since SV is one of target dialects. So the name "LTLToCore" might not fit if we create SV always for verif assert? My impression was rather LTL and Verif are close to core dialect. The pass looks like legalization for btor emission so maybe "PrepareForBtor2Emission"? Sorry for bikeshedding but let me know what you think.

//CHECK: %5 = comb.xor bin %4, %true : i1
%10 = comb.xor bin %9, %true : i1

//CHECK: %6 = hw.wire %0 : i1
Copy link
Member

Choose a reason for hiding this comment

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

What is this wire for?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure, but it's getting generated somewhere outside of my pipeline

Copy link
Contributor

Choose a reason for hiding this comment

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

I would delete the hw.wire lines from the test, since your conversion doesn't explicitly do anything with them, so they don't add anything to the test.

//CHECK: %false = hw.constant false
//CHECK: %true_0 = hw.constant true
//CHECK: %2 = comb.or %reset, %hbr : i1
//CHECK: %hbr = seq.compreg sym @hbr %2, %clock powerOn %false : i1
Copy link
Member

Choose a reason for hiding this comment

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

Why does the pass add a symbol?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because the current build API doesn't allow me to give the register a powerOn Value without also giving it a symbol...

Copy link
Contributor

Choose a reason for hiding this comment

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

The default builder might help. See comment above.

lib/Conversion/LTLToCore/LTLToCore.cpp Outdated Show resolved Hide resolved
lib/Conversion/LTLToCore/LTLToCore.cpp Outdated Show resolved Hide resolved
lib/Conversion/LTLToCore/LTLToCore.cpp Outdated Show resolved Hide resolved
@dobios
Copy link
Member Author

dobios commented May 1, 2024

@uenoku

Thank you for working on this! Looks promising! A few highlevel comments:

1. I'm slightly nervous about having two lowering paths for hasBeenReset op in LTLToCore and VerifToSV. It is possible to unify them? I'm not sure the current two implementations are exactly same behavior in verilog though(LTLToCore lowers a reset value to power-on reset whereas LTLToVerif lowers it to initial statement).

My lowering currently does something similar to the VerifToSV specifically for the HasBeenReset. However, VerifToSV lowers this to sv operations that map neatly to SVA constructs when possible, which is not the case in my lowering which is explicitly avoiding any SVA so that it can be used in any simulator as well as in the formal backend. So I don't think that unifying the two lowerings right now is a useful thing to do, as it would require removing the hasbeenreset lowering from both passes and have it in its own pass that just lowers hasbeenreset (which seems silly to me).

2. I think SV doesn't belong to core dialects since SV is one of target dialects. So the name "LTLToCore" might not fit if we create SV always for verif assert? My impression was rather LTL and Verif are close to core dialect. The pass looks like legalization for btor emission so maybe "PrepareForBtor2Emission"?  Sorry for bikeshedding but let me know what you think.

The reason why I'm using sv.alwaysand sv.assert is that that is currently what is generated when lowering FIRRTL to HW or the Core dialects. Given that those are the only SV operations I generate, I don't think that calling it LTLToSV is a good idea, as this is meant to lower LTL to a state where it can be picked up by the formal backend and not necessarily one that is especially useful for SV. Also I don't want to call it prepare for btro2 as it has use outside of btor2, it makes LTL constructs usable in simulators that don't support property assertions or assertion disabling. The goal is also to extend this pass to lower some basic SVA properties using it.

@dobios dobios requested review from uenoku and dtzSiFive May 1, 2024 22:57
Copy link
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.

Really cool to see this conversion!

The fact that you had to use SV ops here suggests that we're missing something in the core dialects (probably Verif). The stuff in here is probably fine to land as is, but it would be good to have a GitHub issue or a follow-up PR add the missing core ops and get rid of the SV ops here again.

Comment on lines 126 to 130
// Finally generate the register to set the backedge
reg.setValue(rewriter.create<seq::CompRegOp>(
op.getLoc(), orReset,
rewriter.createOrFold<seq::ToClockOp>(op.getLoc(), adaptor.getClock()),
reset, resetval, llvm::StringRef("hbr"), constZero));
Copy link
Contributor

Choose a reason for hiding this comment

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

You might be able to use the default builder instead, which accepts a parameter for every operand and attribute:

  // SeqOps.td: CompRegOp
  let arguments = (ins
    AnyType:$input,
    ClockType:$clk,
    OptionalAttr<StrAttr>:$name,
    Optional<I1>:$reset,
    Optional<AnyType>:$resetValue,
    Optional<AnyType>:$powerOnValue,
    OptionalAttr<InnerSymAttr>:$inner_sym
  );

Something like the following could work:

Suggested change
// Finally generate the register to set the backedge
reg.setValue(rewriter.create<seq::CompRegOp>(
op.getLoc(), orReset,
rewriter.createOrFold<seq::ToClockOp>(op.getLoc(), adaptor.getClock()),
reset, resetval, llvm::StringRef("hbr"), constZero));
// Finally generate the register to set the backedge
reg.setValue(rewriter.create<seq::CompRegOp>(
op.getLoc(),
orReset,
rewriter.createOrFold<seq::ToClockOp>(op.getLoc(), adaptor.getClock()),
StringAttr{}, // name (could also be rewriter.getStringAttr("hbr"))
reset,
resetval,
constZero,
InnerSymAttr{} // inner_sym
));

//CHECK: %false = hw.constant false
//CHECK: %true_0 = hw.constant true
//CHECK: %2 = comb.or %reset, %hbr : i1
//CHECK: %hbr = seq.compreg sym @hbr %2, %clock powerOn %false : i1
Copy link
Contributor

Choose a reason for hiding this comment

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

The default builder might help. See comment above.

//CHECK: %5 = comb.xor bin %4, %true : i1
%10 = comb.xor bin %9, %true : i1

//CHECK: %6 = hw.wire %0 : i1
Copy link
Contributor

Choose a reason for hiding this comment

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

I would delete the hw.wire lines from the test, since your conversion doesn't explicitly do anything with them, so they don't add anything to the test.

test/Conversion/LTLToCore/assertproperty.mlir Outdated Show resolved Hide resolved
@dobios
Copy link
Member Author

dobios commented May 2, 2024

Thanks for the reviews ! Hopefully we can find a good solution for #6982 that solves this unwanted reliance on sv.assert instead of verif.assert in a future PR.

@dobios dobios merged commit d090c66 into main May 2, 2024
4 checks passed
@dobios dobios deleted the dev/dobios/assertproperty-lowering branch May 2, 2024 19:57
@uenoku
Copy link
Member

uenoku commented May 3, 2024

Sorry for late review and it looks good to me, thank you for pushing on this!

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