-
Notifications
You must be signed in to change notification settings - Fork 404
[Datapath] Add Datapath to SMT conversion pass #8682
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
[Datapath] Add Datapath to SMT conversion pass #8682
Conversation
fabianschuiki
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.
Really cool! Just a few minor test regex nits.
|
|
||
| namespace circt { | ||
|
|
||
| /// Get the HW to SMT conversion patterns. |
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.
| /// Get the HW to SMT conversion patterns. | |
| /// Get the Datapath to SMT conversion patterns. |
| // Create free variables | ||
| SmallVector<Value, 2> newResults; | ||
| for (Value result : results) { | ||
| auto declareFunOp = rewriter.create<smt::DeclareFunOp>( | ||
| op.getLoc(), typeConverter->convertType(result.getType())); | ||
| newResults.push_back(declareFunOp.getResult()); | ||
| } |
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.
Very neat 🥳
| //CHECK-NEXT: %[[ADD012:.+]] = smt.bv.add %[[ADD01]], %[[PP2]] : !smt.bv<3> | ||
| //CHECK-NEXT: %[[P:.+]] = smt.eq %[[MUL]], %[[ADD012]] : !smt.bv<3> | ||
| //CHECK-NEXT: smt.assert %[[P]] | ||
| //CHECK-NEXT: hw.output %[[PP0_BV:.+]], %[[PP1_BV:.+]], %[[PP2_BV:.+]] : i3, i3, i3 |
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.
| //CHECK-NEXT: hw.output %[[PP0_BV:.+]], %[[PP1_BV:.+]], %[[PP2_BV:.+]] : i3, i3, i3 | |
| //CHECK-NEXT: hw.output %[[PP0_BV]], %[[PP1_BV]], %[[PP2_BV]] : i3, i3, i3 |
| // CHECK-NEXT: %[[COMP0:.+]] = smt.declare_fun : !smt.bv<4> | ||
| // CHECK-NEXT: %[[COMP0_BV:.+]] = builtin.unrealized_conversion_cast %[[COMP0]] : !smt.bv<4> to i4 | ||
| // CHECK-NEXT: %[[COMP1:.+]] = smt.declare_fun : !smt.bv<4> | ||
| // CHECK-NEXT: %[[COMP1_BV:.+]] = builtin.unrealized_conversion_cast %7 : !smt.bv<4> to i4 |
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.
| // CHECK-NEXT: %[[COMP1_BV:.+]] = builtin.unrealized_conversion_cast %7 : !smt.bv<4> to i4 | |
| // CHECK-NEXT: %[[COMP1_BV:.+]] = builtin.unrealized_conversion_cast %[[COMP1]] : !smt.bv<4> to i4 |
| //CHECK-NEXT: %[[PP0:.+]] = smt.declare_fun : !smt.bv<3> | ||
| //CHECK-NEXT: %[[PP0_BV:.+]] = builtin.unrealized_conversion_cast %3 : !smt.bv<3> to i3 | ||
| //CHECK-NEXT: %[[PP1:.+]] = smt.declare_fun : !smt.bv<3> | ||
| //CHECK-NEXT: %[[PP1_BV:.+]] = builtin.unrealized_conversion_cast %5 : !smt.bv<3> to i3 | ||
| //CHECK-NEXT: %[[PP2:.+]] = smt.declare_fun : !smt.bv<3> | ||
| //CHECK-NEXT: %[[PP2_BV:.+]] = builtin.unrealized_conversion_cast %7 : !smt.bv<3> to i3 |
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.
| //CHECK-NEXT: %[[PP0:.+]] = smt.declare_fun : !smt.bv<3> | |
| //CHECK-NEXT: %[[PP0_BV:.+]] = builtin.unrealized_conversion_cast %3 : !smt.bv<3> to i3 | |
| //CHECK-NEXT: %[[PP1:.+]] = smt.declare_fun : !smt.bv<3> | |
| //CHECK-NEXT: %[[PP1_BV:.+]] = builtin.unrealized_conversion_cast %5 : !smt.bv<3> to i3 | |
| //CHECK-NEXT: %[[PP2:.+]] = smt.declare_fun : !smt.bv<3> | |
| //CHECK-NEXT: %[[PP2_BV:.+]] = builtin.unrealized_conversion_cast %7 : !smt.bv<3> to i3 | |
| //CHECK-NEXT: %[[PP0:.+]] = smt.declare_fun : !smt.bv<3> | |
| //CHECK-NEXT: %[[PP0_BV:.+]] = builtin.unrealized_conversion_cast %[[PP0]] : !smt.bv<3> to i3 | |
| //CHECK-NEXT: %[[PP1:.+]] = smt.declare_fun : !smt.bv<3> | |
| //CHECK-NEXT: %[[PP1_BV:.+]] = builtin.unrealized_conversion_cast %[[PP1]] : !smt.bv<3> to i3 | |
| //CHECK-NEXT: %[[PP2:.+]] = smt.declare_fun : !smt.bv<3> | |
| //CHECK-NEXT: %[[PP2_BV:.+]] = builtin.unrealized_conversion_cast %[[PP2]] : !smt.bv<3> to i3 |
| #include "circt/Conversion/DatapathToSMT.h" | ||
| #include "circt/Conversion/HWToSMT.h" | ||
| #include "circt/Dialect/Datapath/DatapathOps.h" | ||
| #include "mlir/Dialect/Func/IR/FuncOps.h" |
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.
Maybe FuncOp is not necessary?
include/circt/Conversion/Passes.td
Outdated
| def ConvertDatapathToSMT : Pass<"convert-datapath-to-smt"> { | ||
| let summary = "Convert datapath ops to SMT ops"; | ||
| let dependentDialects = [ | ||
| "mlir::smt::SMTDialect", "hw::HWDialect", "mlir::func::FuncDialect" |
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.
hw and func would be not necessary
uenoku
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.
LGTM
| rewriter.create<smt::BVAddOp>(op.getLoc(), operandRunner, operand); | ||
|
|
||
| // Create free variables | ||
| SmallVector<Value, 2> newResults; |
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.
nit:
| SmallVector<Value, 2> newResults; | |
| SmallVector<Value, 2> newResults; | |
| newResults.reserve(results.size()); |
|
Comments addresssed and ready to merge when someone gets a chance please! |
|
Awesome thanks! Landed 👍 |
To verify correctness of transformations involving datapath operations, include a lowering from datapath to SMT. Will later be integrated into circt-lec to enable verification of these operators. Each operator satisfied a contract, rather than providing a precise semantics for every operator. This is because the datapath operators return values in redundant number representations, meaning there are many valid implementations.
For example:
Will be verified by introducing free variables for each return value (%0#0, %0#1) then asserting that the sum of the associated free variables is equal to the sum of the inputs:
assert(%0#0 + %0#1 == %a + %b + %c).Whilst this is encoded as an assert it really represents an assumption that must be satisfied by a valid implementation of datapath.compress.