14#include "llvm/ADT/ArrayRef.h"
15#include "llvm/ADT/SmallVector.h"
16#include "llvm/Support/ErrorHandling.h"
17#include "llvm/Support/SMTAPI.h"
19#ifdef CIRCT_CADICAL_ENABLED
20#include "third_party/cadical/cadical.hpp"
35#ifdef CIRCT_CADICAL_ENABLED
49 llvm_unreachable(
"unknown CaDiCaL configuration");
52class CadicalSATSolver :
public IncrementalSATSolver {
54 explicit CadicalSATSolver(
const CadicalSATSolverOptions &options) {
56 CadicalSATSolverOptions::CadicalSolverConfig::Default) {
57 bool configured = solver.configure(toCadicalConfigName(options.config));
58 assert(configured &&
"invalid CaDiCaL configuration");
62 void add(
int lit)
override { solver.add(
lit); }
63 void assume(
int lit)
override {
67 Result
solve()
override {
68 if (conflictLimit >= 0)
69 solver.limit(
"conflicts", conflictLimit);
70 switch (solver.solve()) {
71 case CaDiCaL::SATISFIABLE:
73 case CaDiCaL::UNSATISFIABLE:
79 int val(
int v)
const override {
80 if (v <= 0 || v > maxVariable)
84 void setConflictLimit(
int limit)
override { conflictLimit = limit; }
85 void reserveVars(
int maxVar)
override {
86 if (maxVar <= maxVariable)
88 solver.resize(maxVar);
91 void addClause(llvm::ArrayRef<int> lits)
override {
96 solver.clause(lits.data(), lits.size());
100 mutable CaDiCaL::Solver solver;
102 int conflictLimit = -1;
113class Z3SATSolver :
public IncrementalSATSolver {
116 ~Z3SATSolver()
override;
118 void add(
int lit)
override;
119 void assume(
int lit)
override;
120 Result
solve()
override;
121 Result
solve(llvm::ArrayRef<int> assumptions)
override;
122 int val(
int v)
const override;
123 void reserveVars(
int maxVar)
override;
126 void clearSolveScope();
128 llvm::SMTExprRef literalToExpr(
int lit);
129 void addClauseInternal(llvm::ArrayRef<int> lits);
131 llvm::SMTSolverRef solver;
132 llvm::SmallVector<llvm::SMTExprRef> variables;
133 llvm::SmallVector<int> assumptions;
134 llvm::SmallVector<int> clauseBuffer;
136 Result lastResult = kUNKNOWN;
137 bool solveScopeActive =
false;
140Z3SATSolver::Z3SATSolver() : solver(
llvm::CreateZ3Solver()) {}
142Z3SATSolver::~Z3SATSolver() { clearSolveScope(); }
144void Z3SATSolver::add(
int lit) {
147 addClauseInternal(clauseBuffer);
148 clauseBuffer.clear();
152 reserveVars(std::abs(
lit));
153 clauseBuffer.push_back(
lit);
156void Z3SATSolver::assume(
int lit) {
160 assumptions.push_back(
lit);
163IncrementalSATSolver::Result Z3SATSolver::solve() {
164 auto localAssumptions = assumptions;
166 return solve(localAssumptions);
169IncrementalSATSolver::Result
170Z3SATSolver::solve(llvm::ArrayRef<int> assumptions) {
173 solveScopeActive =
true;
174 for (
int lit : assumptions)
175 solver->addConstraint(literalToExpr(
lit));
176 auto result = solver->check();
178 return lastResult = kUNKNOWN;
180 return lastResult = kSAT;
181 return lastResult = kUNSAT;
184int Z3SATSolver::val(
int v)
const {
185 if (lastResult != kSAT || v <= 0 || v > maxVariable)
187 llvm::APSInt value(llvm::APInt(1, 0),
true);
191 if (!solver->getInterpretation(variables[v - 1], value))
193 return value != 0 ? v : -v;
196void Z3SATSolver::reserveVars(
int maxVar) {
197 if (maxVar <= maxVariable)
199 while (
static_cast<int>(variables.size()) < maxVar)
201 maxVariable = maxVar;
204void Z3SATSolver::clearSolveScope() {
205 if (!solveScopeActive)
208 solveScopeActive =
false;
209 lastResult = kUNKNOWN;
212int Z3SATSolver::newVariable() {
213 int varIndex =
static_cast<int>(variables.size()) + 1;
214 std::string name =
"v" + std::to_string(varIndex);
215 variables.push_back(solver->mkSymbol(name.c_str(), solver->getBoolSort()));
219llvm::SMTExprRef Z3SATSolver::literalToExpr(
int lit) {
220 int absLit = std::abs(
lit);
223 auto *variable = variables[absLit - 1];
224 return lit > 0 ? variable : solver->mkNot(variable);
227void Z3SATSolver::addClauseInternal(llvm::ArrayRef<int> lits) {
229 solver->addConstraint(solver->mkBoolean(
false));
233 llvm::SMTExprRef clause =
nullptr;
234 for (
int lit : lits) {
237 auto *expr = literalToExpr(
lit);
238 clause = clause ? solver->mkOr(clause, expr) : expr;
242 solver->addConstraint(solver->mkBoolean(
false));
245 solver->addConstraint(clause);
254 return std::make_unique<Z3SATSolver>();
260std::unique_ptr<IncrementalSATSolver>
262#ifdef CIRCT_CADICAL_ENABLED
263 return std::make_unique<CadicalSATSolver>(options);
assert(baseType &&"element must be base type")
static void solve(PassGlobals &globals, Term *lhs, Term *rhs)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
bool hasIncrementalSATSolverBackend()
Return true when at least one incremental SAT backend is available.
std::unique_ptr< IncrementalSATSolver > createZ3SATSolver()
Construct a Z3-backed incremental IPASIR-style SAT solver.
std::unique_ptr< IncrementalSATSolver > createCadicalSATSolver(const CadicalSATSolverOptions &options={})
Construct a CaDiCaL-backed incremental IPASIR-style SAT solver.