17 #include "mlir/IR/Builders.h"
21 #define DEBUG_TYPE "lec-solver"
23 using namespace circt;
27 : circuits{}, mlirCtx(mlirCtx), context(), solver(context),
28 statisticsOpt(statisticsOpt) {}
41 LogicalResult outcome = success();
53 lec::errs() <<
"circt-lec error: solver ran out of time\n";
73 std::string prefix = n == 0 ?
"c1@" :
"c2@";
82 z3::model model =
solver.get_model();
83 for (
unsigned int i = 0; i < model.size(); i++) {
86 z3::func_decl f = model.get_const_decl(i);
88 std::string symbolStr = f.name().str();
89 StringAttr symbol =
builder.getStringAttr(symbolStr);
91 z3::expr e = model.get_const_interp(f);
92 emitRemark(
value.getLoc(),
"");
94 if (
auto arg =
value.dyn_cast<BlockArgument>()) {
96 Operation *parentOp =
value.getParentRegion()->getParentOp();
97 if (
auto op = llvm::dyn_cast<hw::HWModuleOp>(parentOp)) {
99 lec::outs() <<
"argument name: " << op.getArgName(arg.getArgNumber())
107 lec::outs() <<
"internal symbol: " << symbol <<
"\n";
108 lec::outs() <<
"model interpretation: " << e.to_string() <<
"\n\n";
118 for (z3::expr assertion :
solver.assertions()) {
119 lec::dbgs() << assertion.to_string() <<
"\n";
126 lec::outs() <<
"SMT solver statistics:\n";
128 z3::stats stats =
solver.statistics();
129 for (
unsigned i = 0; i < stats.size(); i++) {
130 lec::outs() << stats.key(i) <<
" : " << stats.uint_value(i) <<
"\n";
144 unsigned nc1Inputs = std::distance(c1Inputs.begin(), c1Inputs.end());
145 unsigned nc2Inputs = std::distance(c2Inputs.begin(), c2Inputs.end());
148 if (nc1Inputs != nc2Inputs) {
149 lec::errs() <<
"circt-lec error: different input arity\n";
153 const auto *c1inIt = c1Inputs.begin();
154 const auto *c2inIt = c2Inputs.begin();
155 for (
unsigned i = 0; i < nc1Inputs; i++) {
157 if (c1inIt->get_sort().bv_size() != c2inIt->get_sort().bv_size()) {
158 lec::errs() <<
"circt-lec error: input #" << i + 1 <<
" type mismatch\n";
162 solver.add(*c1inIt++ == *c2inIt++);
167 unsigned nc1Outputs = std::distance(c1Outputs.begin(), c1Outputs.end());
168 unsigned nc2Outputs = std::distance(c2Outputs.begin(), c2Outputs.end());
171 if (nc1Outputs != nc2Outputs) {
172 lec::errs() <<
"circt-lec error: different output arity\n";
176 z3::expr_vector outputTerms(
context);
178 const auto *c1outIt = c1Outputs.begin();
179 const auto *c2outIt = c2Outputs.begin();
180 for (
unsigned i = 0; i < nc1Outputs; i++) {
182 if (c1outIt->get_sort().bv_size() != c2outIt->get_sort().bv_size()) {
183 lec::errs() <<
"circt-lec error: output #" << i + 1 <<
" type mismatch\n";
187 outputTerms.push_back(*c1outIt++ != *c2outIt++);
191 solver.add(z3::mk_or(outputTerms));
assert(baseType &&"element must be base type")
The representation of a circuit within a logical engine.
llvm::ArrayRef< z3::expr > getOutputs()
Recover the outputs.
llvm::ArrayRef< z3::expr > getInputs()
Recover the inputs.
mlir::LogicalResult constrainCircuits()
Formulates additional constraints which are satisfiable if only if the two circuits which are being c...
void printAssertions()
Prints the constraints which were added to the solver.
Circuit * circuits[2]
The two circuits to be compared.
z3::context context
The Z3 context of reference, owning all the declared values, constants and expressions.
void printModel()
Prints a model satisfying the solved constraints.
llvm::DenseMap< mlir::StringAttr, mlir::Value > symbolTable
A map from internal solver symbols to the IR values they represent.
mlir::LogicalResult solve()
Solve the equivalence problem between the two circuits, then present the results to the user.
Circuit * addCircuit(llvm::StringRef name)
Create a new circuit to be compared and return it.
mlir::MLIRContext * mlirCtx
The MLIR context of reference, owning all the MLIR entities.
bool statisticsOpt
The value of the statistics command-line option.
void printStatistics()
Prints the internal statistics of the SMT solver for benchmarking purposes and operational insight.
Solver(mlir::MLIRContext *mlirCtx, bool statisticsOpt)
z3::solver solver
The Z3 solver acting as the logical engine backend.
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
mlir::raw_indented_ostream & outs()
mlir::raw_indented_ostream & errs()
mlir::raw_indented_ostream & dbgs()
RAII struct to indent the output streams.