*/
#include "kernel/yosys.h"
+#include "kernel/satgen.h"
+
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
log("echo %s\n", echo_mode ? "on" : "off");
}
} EchoPass;
+
+SatSolver *yosys_satsolver_list;
+SatSolver *yosys_satsolver;
+
+struct MinisatSatSolver : public SatSolver {
+ MinisatSatSolver() : SatSolver("minisat") {
+ yosys_satsolver = this;
+ }
+ virtual ezSAT *create() YS_OVERRIDE {
+ return new ezMiniSAT();
+ }
+} MinisatSatSolver;
YOSYS_NAMESPACE_END
YOSYS_NAMESPACE_BEGIN
-typedef ezMiniSAT ezDefaultSAT;
+// defined in kernel/register.cc
+extern struct SatSolver *yosys_satsolver_list;
+extern struct SatSolver *yosys_satsolver;
+
+struct SatSolver
+{
+ string name;
+ SatSolver *next;
+ virtual ezSAT *create() = 0;
+
+ SatSolver(string name) : name(name) {
+ next = yosys_satsolver_list;
+ yosys_satsolver_list = this;
+ }
+
+ virtual ~SatSolver() {
+ auto p = &yosys_satsolver_list;
+ while (*p) {
+ if (*p == this)
+ *p = next;
+ else
+ p = &(*p)->next;
+ }
+ if (yosys_satsolver == this)
+ yosys_satsolver = yosys_satsolver_list;
+ }
+};
+
+struct ezSatPtr : public std::unique_ptr<ezSAT> {
+ ezSatPtr() : unique_ptr<ezSAT>(yosys_satsolver->create()) { }
+};
struct SatGen
{
#include <unordered_set>
#include <initializer_list>
#include <stdexcept>
+#include <memory>
#include <sstream>
#include <fstream>
vector<Cell*> cells;
pool<Cell*> workset;
- ezDefaultSAT ez;
+ ezSatPtr ez;
SatGen satgen;
int max_seq;
SigPool undriven_signals;
EquivInductWorker(Module *module, const pool<Cell*> &unproven_equiv_cells, bool model_undef, int max_seq) : module(module), sigmap(module),
- cells(module->selected_cells()), workset(unproven_equiv_cells), satgen(&ez, &sigmap), max_seq(max_seq), success_counter(0)
+ cells(module->selected_cells()), workset(unproven_equiv_cells),
+ satgen(ez.get(), &sigmap), max_seq(max_seq), success_counter(0)
{
satgen.model_undef = model_undef;
}
if (bit_a != bit_b) {
int ez_a = satgen.importSigBit(bit_a, step);
int ez_b = satgen.importSigBit(bit_b, step);
- int cond = ez.IFF(ez_a, ez_b);
+ int cond = ez->IFF(ez_a, ez_b);
if (satgen.model_undef)
- cond = ez.OR(cond, satgen.importUndefSigBit(bit_a, step));
+ cond = ez->OR(cond, satgen.importUndefSigBit(bit_a, step));
ez_equal_terms.push_back(cond);
}
}
if (satgen.model_undef) {
for (auto bit : undriven_signals.export_all())
- ez.assume(ez.NOT(satgen.importUndefSigBit(bit, step)));
+ ez->assume(ez->NOT(satgen.importUndefSigBit(bit, step)));
}
log_assert(!ez_step_is_consistent.count(step));
- ez_step_is_consistent[step] = ez.expression(ez.OpAnd, ez_equal_terms);
+ ez_step_is_consistent[step] = ez->expression(ez->OpAnd, ez_equal_terms);
}
void run()
if (satgen.model_undef) {
for (auto bit : satgen.initial_state.export_all())
- ez.assume(ez.NOT(satgen.importUndefSigBit(bit, 1)));
+ ez->assume(ez->NOT(satgen.importUndefSigBit(bit, 1)));
log(" Undef modelling: force def on %d initial reg values and %d inputs.\n",
GetSize(satgen.initial_state), GetSize(undriven_signals));
}
for (int step = 1; step <= max_seq; step++)
{
- ez.assume(ez_step_is_consistent[step]);
+ ez->assume(ez_step_is_consistent[step]);
- log(" Proving existence of base case for step %d. (%d clauses over %d variables)\n", step, ez.numCnfClauses(), ez.numCnfVariables());
- if (!ez.solve()) {
+ log(" Proving existence of base case for step %d. (%d clauses over %d variables)\n", step, ez->numCnfClauses(), ez->numCnfVariables());
+ if (!ez->solve()) {
log(" Proof for base case failed. Circuit inherently diverges!\n");
return;
}
create_timestep(step+1);
- int new_step_not_consistent = ez.NOT(ez_step_is_consistent[step+1]);
- ez.bind(new_step_not_consistent);
+ int new_step_not_consistent = ez->NOT(ez_step_is_consistent[step+1]);
+ ez->bind(new_step_not_consistent);
- log(" Proving induction step %d. (%d clauses over %d variables)\n", step, ez.numCnfClauses(), ez.numCnfVariables());
- if (!ez.solve(new_step_not_consistent)) {
+ log(" Proving induction step %d. (%d clauses over %d variables)\n", step, ez->numCnfClauses(), ez->numCnfVariables());
+ if (!ez->solve(new_step_not_consistent)) {
log(" Proof for induction step holds. Entire workset of %d cells proven!\n", GetSize(workset));
for (auto cell : workset)
cell->setPort("\\B", cell->getPort("\\A"));
int ez_a = satgen.importSigBit(bit_a, max_seq+1);
int ez_b = satgen.importSigBit(bit_b, max_seq+1);
- int cond = ez.XOR(ez_a, ez_b);
+ int cond = ez->XOR(ez_a, ez_b);
if (satgen.model_undef)
- cond = ez.AND(cond, ez.NOT(satgen.importUndefSigBit(bit_a, max_seq+1)));
+ cond = ez->AND(cond, ez->NOT(satgen.importUndefSigBit(bit_a, max_seq+1)));
- if (!ez.solve(cond)) {
+ if (!ez->solve(cond)) {
log(" success!\n");
cell->setPort("\\B", cell->getPort("\\A"));
success_counter++;
SigMap &sigmap;
dict<SigBit, Cell*> &bit2driver;
- ezDefaultSAT ez;
+ ezSatPtr ez;
SatGen satgen;
int max_seq;
bool verbose;
EquivSimpleWorker(const vector<Cell*> &equiv_cells, SigMap &sigmap, dict<SigBit, Cell*> &bit2driver, int max_seq, bool verbose, bool model_undef) :
module(equiv_cells.front()->module), equiv_cells(equiv_cells), equiv_cell(nullptr),
- sigmap(sigmap), bit2driver(bit2driver), satgen(&ez, &sigmap), max_seq(max_seq), verbose(verbose)
+ sigmap(sigmap), bit2driver(bit2driver), satgen(ez.get(), &sigmap), max_seq(max_seq), verbose(verbose)
{
satgen.model_undef = model_undef;
}
{
SigBit bit_a = sigmap(equiv_cell->getPort("\\A")).to_single_sigbit();
SigBit bit_b = sigmap(equiv_cell->getPort("\\B")).to_single_sigbit();
- int ez_context = ez.frozen_literal();
+ int ez_context = ez->frozen_literal();
if (satgen.model_undef)
{
int ez_b = satgen.importDefSigBit(bit_b, max_seq+1);
int ez_undef_a = satgen.importUndefSigBit(bit_a, max_seq+1);
- ez.assume(ez.XOR(ez_a, ez_b), ez_context);
- ez.assume(ez.NOT(ez_undef_a), ez_context);
+ ez->assume(ez->XOR(ez_a, ez_b), ez_context);
+ ez->assume(ez->NOT(ez_undef_a), ez_context);
}
else
{
int ez_a = satgen.importSigBit(bit_a, max_seq+1);
int ez_b = satgen.importSigBit(bit_b, max_seq+1);
- ez.assume(ez.XOR(ez_a, ez_b), ez_context);
+ ez->assume(ez->XOR(ez_a, ez_b), ez_context);
}
pool<SigBit> seed_a = { bit_a };
if (satgen.model_undef) {
for (auto bit : input_bits)
- ez.assume(ez.NOT(satgen.importUndefSigBit(bit, step+1)));
+ ez->assume(ez->NOT(satgen.importUndefSigBit(bit, step+1)));
}
if (verbose)
- log(" Problem size at t=%d: %d literals, %d clauses\n", step, ez.numCnfVariables(), ez.numCnfClauses());
+ log(" Problem size at t=%d: %d literals, %d clauses\n", step, ez->numCnfVariables(), ez->numCnfClauses());
- if (!ez.solve(ez_context)) {
+ if (!ez->solve(ez_context)) {
log(verbose ? " Proved equivalence! Marking $equiv cell as proven.\n" : " success!\n");
equiv_cell->setPort("\\B", equiv_cell->getPort("\\A"));
- ez.assume(ez.NOT(ez_context));
+ ez->assume(ez->NOT(ez_context));
return true;
}
if (!verbose)
log(" failed.\n");
- ez.assume(ez.NOT(ez_context));
+ ez->assume(ez->NOT(ez_context));
return false;
}
if (wr_ports.size() <= 1)
return;
- ezDefaultSAT ez;
- SatGen satgen(&ez, &modwalker.sigmap);
+ ezSatPtr ez;
+ SatGen satgen(ez.get(), &modwalker.sigmap);
// find list of considered ports and port pairs
if (considered_port_pairs.count(i) || considered_port_pairs.count(i+1))
{
RTLIL::SigSpec sig = modwalker.sigmap(wr_ports[i]->getPort("\\EN"));
- port_to_sat_variable[i] = ez.expression(ez.OpOr, satgen.importSigSpec(sig));
+ port_to_sat_variable[i] = ez->expression(ez->OpOr, satgen.importSigSpec(sig));
std::vector<RTLIL::SigBit> bits = sig;
bits_queue.insert(bits.begin(), bits.end());
vector<int> ez_wire_bits = satgen.importSigSpec(wire);
for (int i : ez_wire_bits)
for (int j : ez_wire_bits)
- if (i != j) ez.assume(ez.NOT(i), j);
+ if (i != j) ez->assume(ez->NOT(i), j);
}
log(" Common input cone for all EN signals: %d cells.\n", int(sat_cells.size()));
for (auto cell : sat_cells)
satgen.importCell(cell);
- log(" Size of unconstrained SAT problem: %d variables, %d clauses\n", ez.numCnfVariables(), ez.numCnfClauses());
+ log(" Size of unconstrained SAT problem: %d variables, %d clauses\n", ez->numCnfVariables(), ez->numCnfClauses());
// merge subsequent ports if possible
if (!considered_port_pairs.count(i))
continue;
- if (ez.solve(port_to_sat_variable.at(i-1), port_to_sat_variable.at(i))) {
+ if (ez->solve(port_to_sat_variable.at(i-1), port_to_sat_variable.at(i))) {
log(" According to SAT solver sharing of port %d with port %d is not possible.\n", i-1, i);
continue;
}
log(" Merging port %d into port %d.\n", i-1, i);
- port_to_sat_variable.at(i) = ez.OR(port_to_sat_variable.at(i-1), port_to_sat_variable.at(i));
+ port_to_sat_variable.at(i) = ez->OR(port_to_sat_variable.at(i-1), port_to_sat_variable.at(i));
RTLIL::SigSpec last_addr = wr_ports[i-1]->getPort("\\ADDR");
RTLIL::SigSpec last_data = wr_ports[i-1]->getPort("\\DATA");
optimize_activation_patterns(filtered_cell_activation_patterns);
optimize_activation_patterns(filtered_other_cell_activation_patterns);
- ezDefaultSAT ez;
- SatGen satgen(&ez, &modwalker.sigmap);
+ ezSatPtr ez;
+ SatGen satgen(ez.get(), &modwalker.sigmap);
pool<RTLIL::Cell*> sat_cells;
std::set<RTLIL::SigBit> bits_queue;
for (auto &p : filtered_cell_activation_patterns) {
log(" Activation pattern for cell %s: %s = %s\n", log_id(cell), log_signal(p.first), log_signal(p.second));
- cell_active.push_back(ez.vec_eq(satgen.importSigSpec(p.first), satgen.importSigSpec(p.second)));
+ cell_active.push_back(ez->vec_eq(satgen.importSigSpec(p.first), satgen.importSigSpec(p.second)));
all_ctrl_signals.append(p.first);
}
for (auto &p : filtered_other_cell_activation_patterns) {
log(" Activation pattern for cell %s: %s = %s\n", log_id(other_cell), log_signal(p.first), log_signal(p.second));
- other_cell_active.push_back(ez.vec_eq(satgen.importSigSpec(p.first), satgen.importSigSpec(p.second)));
+ other_cell_active.push_back(ez->vec_eq(satgen.importSigSpec(p.first), satgen.importSigSpec(p.second)));
all_ctrl_signals.append(p.first);
}
log(" Adding exclusive control bits: %s vs. %s\n", log_signal(it.first), log_signal(it.second));
int sub1 = satgen.importSigBit(it.first);
int sub2 = satgen.importSigBit(it.second);
- ez.assume(ez.NOT(ez.AND(sub1, sub2)));
+ ez->assume(ez->NOT(ez->AND(sub1, sub2)));
}
- if (!ez.solve(ez.expression(ez.OpOr, cell_active))) {
+ if (!ez->solve(ez->expression(ez->OpOr, cell_active))) {
log(" According to the SAT solver the cell %s is never active. Sharing is pointless, we simply remove it.\n", log_id(cell));
cells_to_remove.insert(cell);
break;
}
- if (!ez.solve(ez.expression(ez.OpOr, other_cell_active))) {
+ if (!ez->solve(ez->expression(ez->OpOr, other_cell_active))) {
log(" According to the SAT solver the cell %s is never active. Sharing is pointless, we simply remove it.\n", log_id(other_cell));
cells_to_remove.insert(other_cell);
shareable_cells.erase(other_cell);
continue;
}
- ez.non_incremental();
+ ez->non_incremental();
all_ctrl_signals.sort_and_unify();
std::vector<int> sat_model = satgen.importSigSpec(all_ctrl_signals);
std::vector<bool> sat_model_values;
- int sub1 = ez.expression(ez.OpOr, cell_active);
- int sub2 = ez.expression(ez.OpOr, other_cell_active);
- ez.assume(ez.AND(sub1, sub2));
+ int sub1 = ez->expression(ez->OpOr, cell_active);
+ int sub2 = ez->expression(ez->OpOr, other_cell_active);
+ ez->assume(ez->AND(sub1, sub2));
log(" Size of SAT problem: %d cells, %d variables, %d clauses\n",
- GetSize(sat_cells), ez.numCnfVariables(), ez.numCnfClauses());
+ GetSize(sat_cells), ez->numCnfVariables(), ez->numCnfClauses());
- if (ez.solve(sat_model, sat_model_values)) {
+ if (ez->solve(sat_model, sat_model_values)) {
log(" According to the SAT solver this pair of cells can not be shared.\n");
log(" Model from SAT solver: %s = %d'", log_signal(all_ctrl_signals), GetSize(sat_model_values));
for (int i = GetSize(sat_model_values)-1; i >= 0; i--)
{
log("Verifying SAT model (%s)..\n", model_undef ? "with undef" : "without undef");
- ezDefaultSAT ez;
+ ezSatPtr ez;
SigMap sigmap(module);
- SatGen satgen(&ez, &sigmap);
+ SatGen satgen(ez.get(), &sigmap);
satgen.model_undef = model_undef;
for (auto &c : module->cells_)
if (!satgen.importCell(c.second))
log_error("Failed to import cell %s (type %s) to SAT database.\n", RTLIL::id2cstr(c.first), RTLIL::id2cstr(c.second->type));
- ez.assume(satgen.signals_eq(recorded_set_vars, recorded_set_vals));
+ ez->assume(satgen.signals_eq(recorded_set_vars, recorded_set_vals));
std::vector<int> y_vec = satgen.importDefSigSpec(module->wires_.at("\\y"));
std::vector<bool> y_values;
}
log(" Created SAT problem with %d variables and %d clauses.\n",
- ez.numCnfVariables(), ez.numCnfClauses());
+ ez->numCnfVariables(), ez->numCnfClauses());
- if (!ez.solve(y_vec, y_values))
+ if (!ez->solve(y_vec, y_values))
log_error("Failed to find solution to SAT problem.\n");
for (int i = 0; i < expected_y.size(); i++) {
if (y_undef.at(i))
{
log(" Toggling undef bit %d to test undef gating.\n", i);
- if (!ez.solve(y_vec, y_values, ez.IFF(y_vec.at(i), y_values.at(i) ? ez.CONST_FALSE : ez.CONST_TRUE)))
+ if (!ez->solve(y_vec, y_values, ez->IFF(y_vec.at(i), y_values.at(i) ? ez->CONST_FALSE : ez->CONST_TRUE)))
log_error("Failed to find solution with toggled bit!\n");
cmp_vars.push_back(y_vec.at(expected_y.size() + i));
}
log(" Testing if SAT solution is unique.\n");
- ez.assume(ez.vec_ne(cmp_vars, ez.vec_const(cmp_vals)));
- if (ez.solve(y_vec, y_values))
+ ez->assume(ez->vec_ne(cmp_vars, ez->vec_const(cmp_vals)));
+ if (ez->solve(y_vec, y_values))
log_error("Found two distinct solutions to SAT problem.\n");
}
else
{
log(" Testing if SAT solution is unique.\n");
- ez.assume(ez.vec_ne(y_vec, ez.vec_const(y_values)));
- if (ez.solve(y_vec, y_values))
+ ez->assume(ez->vec_ne(y_vec, ez->vec_const(y_values)));
+ if (ez->solve(y_vec, y_values))
log_error("Found two distinct solutions to SAT problem.\n");
}
SigMap &sigmap;
drivers_t &drivers;
- ezDefaultSAT ez;
+ ezSatPtr ez;
std::set<RTLIL::Cell*> ez_cells;
SatGen satgen;
std::vector<int> sat_pi_uniq_bitvec;
FindReducedInputs(SigMap &sigmap, drivers_t &drivers) :
- sigmap(sigmap), drivers(drivers), satgen(&ez, &sigmap)
+ sigmap(sigmap), drivers(drivers), satgen(ez.get(), &sigmap)
{
satgen.model_undef = true;
}
satgen.setContext(&sigmap, "A");
int sat_a = satgen.importSigSpec(bit).front();
- ez.assume(ez.NOT(satgen.importUndefSigSpec(bit).front()));
+ ez->assume(ez->NOT(satgen.importUndefSigSpec(bit).front()));
satgen.setContext(&sigmap, "B");
int sat_b = satgen.importSigSpec(bit).front();
- ez.assume(ez.NOT(satgen.importUndefSigSpec(bit).front()));
+ ez->assume(ez->NOT(satgen.importUndefSigSpec(bit).front()));
int idx = sat_pi.size();
size_t idx_bits = get_bits(idx);
if (sat_pi_uniq_bitvec.size() != idx_bits) {
- sat_pi_uniq_bitvec.push_back(ez.frozen_literal(stringf("uniq_%d", int(idx_bits)-1)));
+ sat_pi_uniq_bitvec.push_back(ez->frozen_literal(stringf("uniq_%d", int(idx_bits)-1)));
for (auto &it : sat_pi)
- ez.assume(ez.OR(ez.NOT(it.second), ez.NOT(sat_pi_uniq_bitvec.back())));
+ ez->assume(ez->OR(ez->NOT(it.second), ez->NOT(sat_pi_uniq_bitvec.back())));
}
log_assert(sat_pi_uniq_bitvec.size() == idx_bits);
- sat_pi[bit] = ez.frozen_literal(stringf("p, falsei_%s", log_signal(bit)));
- ez.assume(ez.IFF(ez.XOR(sat_a, sat_b), sat_pi[bit]));
+ sat_pi[bit] = ez->frozen_literal(stringf("p, falsei_%s", log_signal(bit)));
+ ez->assume(ez->IFF(ez->XOR(sat_a, sat_b), sat_pi[bit]));
for (size_t i = 0; i < idx_bits; i++)
if ((idx & (1 << i)) == 0)
- ez.assume(ez.OR(ez.NOT(sat_pi[bit]), ez.NOT(sat_pi_uniq_bitvec[i])));
+ ez->assume(ez->OR(ez->NOT(sat_pi[bit]), ez->NOT(sat_pi_uniq_bitvec[i])));
else
- ez.assume(ez.OR(ez.NOT(sat_pi[bit]), sat_pi_uniq_bitvec[i]));
+ ez->assume(ez->OR(ez->NOT(sat_pi[bit]), sat_pi_uniq_bitvec[i]));
}
void register_cone_worker(std::set<RTLIL::SigBit> &pi, std::set<RTLIL::SigBit> &sigdone, RTLIL::SigBit out)
model_expr.push_back(sat_pi.at(pi[i]));
}
- if (!ez.solve(model_expr, model, ez.expression(ezSAT::OpOr, model_expr), ez.XOR(output_a, output_b), ez.NOT(output_undef_a), ez.NOT(output_undef_b)))
+ if (!ez->solve(model_expr, model, ez->expression(ezSAT::OpOr, model_expr), ez->XOR(output_a, output_b), ez->NOT(output_undef_a), ez->NOT(output_undef_b)))
break;
int found_count = 0;
drivers_t &drivers;
std::set<std::pair<RTLIL::SigBit, RTLIL::SigBit>> &inv_pairs;
- ezDefaultSAT ez;
+ ezSatPtr ez;
SatGen satgen;
std::vector<int> sat_pi, sat_out, sat_def;
} else {
pi_bits.push_back(out);
sat_pi.push_back(satgen.importSigSpec(out).front());
- ez.assume(ez.NOT(satgen.importUndefSigSpec(out).front()));
+ ez->assume(ez->NOT(satgen.importUndefSigSpec(out).front()));
sigdepth[out] = 0;
}
}
PerformReduction(SigMap &sigmap, drivers_t &drivers, std::set<std::pair<RTLIL::SigBit, RTLIL::SigBit>> &inv_pairs, std::vector<RTLIL::SigBit> &bits, int cone_size) :
- sigmap(sigmap), drivers(drivers), inv_pairs(inv_pairs), satgen(&ez, &sigmap), out_bits(bits), cone_size(cone_size)
+ sigmap(sigmap), drivers(drivers), inv_pairs(inv_pairs), satgen(ez.get(), &sigmap), out_bits(bits), cone_size(cone_size)
{
satgen.model_undef = true;
for (auto &bit : bits) {
out_depth.push_back(register_cone_worker(celldone, sigdepth, bit));
sat_out.push_back(satgen.importSigSpec(bit).front());
- sat_def.push_back(ez.NOT(satgen.importUndefSigSpec(bit).front()));
+ sat_def.push_back(ez->NOT(satgen.importUndefSigSpec(bit).front()));
}
if (inv_mode && cone_size > 0) {
- if (!ez.solve(sat_out, out_inverted, ez.expression(ezSAT::OpAnd, sat_def)))
+ if (!ez->solve(sat_out, out_inverted, ez->expression(ezSAT::OpAnd, sat_def)))
log_error("Solving for initial model failed!\n");
for (size_t i = 0; i < sat_out.size(); i++)
if (out_inverted.at(i))
- sat_out[i] = ez.NOT(sat_out[i]);
+ sat_out[i] = ez->NOT(sat_out[i]);
} else
out_inverted = std::vector<bool>(sat_out.size(), false);
}
if (verbose_level == 1)
log(" Finding const value for %s.\n", log_signal(out_bits[idx]));
- bool can_be_set = ez.solve(ez.AND(sat_out[idx], sat_def[idx]));
- bool can_be_clr = ez.solve(ez.AND(ez.NOT(sat_out[idx]), sat_def[idx]));
+ bool can_be_set = ez->solve(ez->AND(sat_out[idx], sat_def[idx]));
+ bool can_be_clr = ez->solve(ez->AND(ez->NOT(sat_out[idx]), sat_def[idx]));
log_assert(!can_be_set || !can_be_clr);
RTLIL::SigBit value(RTLIL::State::Sx);
std::vector<int> sat_set_list, sat_clr_list;
for (int idx : bucket) {
- sat_set_list.push_back(ez.AND(sat_out[idx], sat_def[idx]));
- sat_clr_list.push_back(ez.AND(ez.NOT(sat_out[idx]), sat_def[idx]));
+ sat_set_list.push_back(ez->AND(sat_out[idx], sat_def[idx]));
+ sat_clr_list.push_back(ez->AND(ez->NOT(sat_out[idx]), sat_def[idx]));
}
std::vector<int> modelVars = sat_out;
if (verbose_level >= 2)
modelVars.insert(modelVars.end(), sat_pi.begin(), sat_pi.end());
- if (ez.solve(modelVars, model, ez.expression(ezSAT::OpOr, sat_set_list), ez.expression(ezSAT::OpOr, sat_clr_list)))
+ if (ez->solve(modelVars, model, ez->expression(ezSAT::OpOr, sat_set_list), ez->expression(ezSAT::OpOr, sat_clr_list)))
{
int iter_count = 1;
for (int idx : bucket)
if (!model[sat_out.size() + idx]) {
- sat_set_list.push_back(ez.AND(sat_out[idx], sat_def[idx]));
- sat_clr_list.push_back(ez.AND(ez.NOT(sat_out[idx]), sat_def[idx]));
+ sat_set_list.push_back(ez->AND(sat_out[idx], sat_def[idx]));
+ sat_clr_list.push_back(ez->AND(ez->NOT(sat_out[idx]), sat_def[idx]));
} else {
sat_def_list.push_back(sat_def[idx]);
}
- if (!ez.solve(modelVars, model, ez.expression(ezSAT::OpOr, sat_set_list), ez.expression(ezSAT::OpOr, sat_clr_list), ez.expression(ezSAT::OpAnd, sat_def_list)))
+ if (!ez->solve(modelVars, model, ez->expression(ezSAT::OpOr, sat_set_list), ez->expression(ezSAT::OpOr, sat_clr_list), ez->expression(ezSAT::OpAnd, sat_def_list)))
break;
iter_count++;
}
for (int idx2 : bucket)
if (idx != idx2)
sat_def_list.push_back(sat_def[idx2]);
- if (ez.solve(ez.NOT(sat_def[idx]), ez.expression(ezSAT::OpOr, sat_def_list)))
+ if (ez->solve(ez->NOT(sat_def[idx]), ez->expression(ezSAT::OpOr, sat_def_list)))
undef_slaves.push_back(idx);
}
for (int idx2 : r)
if (idx != idx2)
sat_def_list.push_back(sat_def[idx2]);
- if (ez.solve(ez.NOT(sat_def[idx]), ez.expression(ezSAT::OpOr, sat_def_list)))
+ if (ez->solve(ez->NOT(sat_def[idx]), ez->expression(ezSAT::OpOr, sat_def_list)))
undef_slaves.push_back(idx);
}
RTLIL::Design *design;
RTLIL::Module *module;
- ezDefaultSAT ez;
SigMap sigmap;
CellTypes ct;
+
+ ezSatPtr ez;
SatGen satgen;
// additional constraints
bool gotTimeout;
SatHelper(RTLIL::Design *design, RTLIL::Module *module, bool enable_undef) :
- design(design), module(module), sigmap(module), ct(design), satgen(&ez, &sigmap)
+ design(design), module(module), sigmap(module), ct(design), satgen(ez.get(), &sigmap)
{
this->enable_undef = enable_undef;
satgen.model_undef = enable_undef;
if (set_init_def) {
RTLIL::SigSpec rem = satgen.initial_state.export_all();
std::vector<int> undef_rem = satgen.importUndefSigSpec(rem, 1);
- ez.assume(ez.NOT(ez.expression(ezSAT::OpOr, undef_rem)));
+ ez->assume(ez->NOT(ez->expression(ezSAT::OpOr, undef_rem)));
}
if (set_init_undef) {
log("Final constraint equation: %s = %s\n\n", log_signal(big_lhs), log_signal(big_rhs));
check_undef_enabled(big_lhs), check_undef_enabled(big_rhs);
- ez.assume(satgen.signals_eq(big_lhs, big_rhs, 1));
+ ez->assume(satgen.signals_eq(big_lhs, big_rhs, 1));
}
void setup(int timestep = -1)
log("Final constraint equation: %s = %s\n", log_signal(big_lhs), log_signal(big_rhs));
check_undef_enabled(big_lhs), check_undef_enabled(big_rhs);
- ez.assume(satgen.signals_eq(big_lhs, big_rhs, timestep));
+ ez->assume(satgen.signals_eq(big_lhs, big_rhs, timestep));
// 0 = sets_def
// 1 = sets_any_undef
log("Import %s constraint for this timestep: %s\n", t == 0 ? "def" : t == 1 ? "any_undef" : "all_undef", log_signal(sig));
std::vector<int> undef_sig = satgen.importUndefSigSpec(sig, timestep);
if (t == 0)
- ez.assume(ez.NOT(ez.expression(ezSAT::OpOr, undef_sig)));
+ ez->assume(ez->NOT(ez->expression(ezSAT::OpOr, undef_sig)));
if (t == 1)
- ez.assume(ez.expression(ezSAT::OpOr, undef_sig));
+ ez->assume(ez->expression(ezSAT::OpOr, undef_sig));
if (t == 2)
- ez.assume(ez.expression(ezSAT::OpAnd, undef_sig));
+ ez->assume(ez->expression(ezSAT::OpAnd, undef_sig));
}
int import_cell_counter = 0;
std::vector<int> undef_rhs = satgen.importUndefSigSpec(big_rhs, timestep);
for (size_t i = 0; i < value_lhs.size(); i++)
- prove_bits.push_back(ez.OR(undef_lhs.at(i), ez.AND(ez.NOT(undef_rhs.at(i)), ez.NOT(ez.XOR(value_lhs.at(i), value_rhs.at(i))))));
+ prove_bits.push_back(ez->OR(undef_lhs.at(i), ez->AND(ez->NOT(undef_rhs.at(i)), ez->NOT(ez->XOR(value_lhs.at(i), value_rhs.at(i))))));
}
if (prove_asserts) {
prove_bits.push_back(satgen.importAsserts(timestep));
}
- return ez.expression(ezSAT::OpAnd, prove_bits);
+ return ez->expression(ezSAT::OpAnd, prove_bits);
}
void force_unique_state(int timestep_from, int timestep_to)
{
RTLIL::SigSpec state_signals = satgen.initial_state.export_all();
for (int i = timestep_from; i < timestep_to; i++)
- ez.assume(ez.NOT(satgen.signals_eq(state_signals, state_signals, i, timestep_to)));
+ ez->assume(ez->NOT(satgen.signals_eq(state_signals, state_signals, i, timestep_to)));
}
bool solve(const std::vector<int> &assumptions)
{
log_assert(gotTimeout == false);
- ez.setSolverTimeout(timeout);
- bool success = ez.solve(modelExpressions, modelValues, assumptions);
- if (ez.getSolverTimoutStatus())
+ ez->setSolverTimeout(timeout);
+ bool success = ez->solve(modelExpressions, modelValues, assumptions);
+ if (ez->getSolverTimoutStatus())
gotTimeout = true;
return success;
}
bool solve(int a = 0, int b = 0, int c = 0, int d = 0, int e = 0, int f = 0)
{
log_assert(gotTimeout == false);
- ez.setSolverTimeout(timeout);
- bool success = ez.solve(modelExpressions, modelValues, a, b, c, d, e, f);
- if (ez.getSolverTimoutStatus())
+ ez->setSolverTimeout(timeout);
+ bool success = ez->solve(modelExpressions, modelValues, a, b, c, d, e, f);
+ if (ez->getSolverTimoutStatus())
gotTimeout = true;
return success;
}
maybe_undef.push_back(modelExpressions.at(modelExpressions.size()/2 + i));
backupValues.swap(modelValues);
- if (!solve(ez.expression(ezSAT::OpAnd, must_undef), ez.expression(ezSAT::OpOr, maybe_undef)))
+ if (!solve(ez->expression(ezSAT::OpAnd, must_undef), ez->expression(ezSAT::OpOr, maybe_undef)))
break;
}
int bit = modelExpressions.at(i), bit_undef = modelExpressions.at(modelExpressions.size()/2 + i);
bool val = modelValues.at(i), val_undef = modelValues.at(modelExpressions.size()/2 + i);
if (!max_undef || !val_undef)
- clause.push_back(val_undef ? ez.NOT(bit_undef) : val ? ez.NOT(bit) : bit);
+ clause.push_back(val_undef ? ez->NOT(bit_undef) : val ? ez->NOT(bit) : bit);
}
} else
for (size_t i = 0; i < modelExpressions.size(); i++)
- clause.push_back(modelValues.at(i) ? ez.NOT(modelExpressions.at(i)) : modelExpressions.at(i));
- ez.assume(ez.expression(ezSAT::OpOr, clause));
+ clause.push_back(modelValues.at(i) ? ez->NOT(modelExpressions.at(i)) : modelExpressions.at(i));
+ ez->assume(ez->expression(ezSAT::OpOr, clause));
}
};
inductstep.ignore_unknown_cells = ignore_unknown_cells;
inductstep.setup(1);
- inductstep.ez.assume(inductstep.setup_proof(1));
+ inductstep.ez->assume(inductstep.setup_proof(1));
if (tempinduct_def) {
std::vector<int> undef_state = inductstep.satgen.importUndefSigSpec(inductstep.satgen.initial_state.export_all(), 1);
- inductstep.ez.assume(inductstep.ez.NOT(inductstep.ez.expression(ezSAT::OpOr, undef_state)));
+ inductstep.ez->assume(inductstep.ez->NOT(inductstep.ez->expression(ezSAT::OpOr, undef_state)));
}
for (int inductlen = 1; inductlen <= maxsteps || maxsteps == 0; inductlen++)
basecase.force_unique_state(seq_len + 1, seq_len + inductlen);
log("\n[base case] Solving problem with %d variables and %d clauses..\n",
- basecase.ez.numCnfVariables(), basecase.ez.numCnfClauses());
+ basecase.ez->numCnfVariables(), basecase.ez->numCnfClauses());
- if (basecase.solve(basecase.ez.NOT(property))) {
+ if (basecase.solve(basecase.ez->NOT(property))) {
log("SAT temporal induction proof finished - model found for base case: FAIL!\n");
print_proof_failed();
basecase.print_model();
goto timeout;
log("Base case for induction length %d proven.\n", inductlen);
- basecase.ez.assume(property);
+ basecase.ez->assume(property);
// phase 2: proving induction step
if (inductlen < initsteps)
{
log("\n[induction step] Skipping problem with %d variables and %d clauses (below initsteps).\n",
- inductstep.ez.numCnfVariables(), inductstep.ez.numCnfClauses());
- inductstep.ez.assume(property);
+ inductstep.ez->numCnfVariables(), inductstep.ez->numCnfClauses());
+ inductstep.ez->assume(property);
}
else
{
log("Dumping CNF to file `%s'.\n", cnf_file_name.c_str());
cnf_file_name.clear();
- inductstep.ez.printDIMACS(f, false);
+ inductstep.ez->printDIMACS(f, false);
fclose(f);
}
log("\n[induction step] Solving problem with %d variables and %d clauses..\n",
- inductstep.ez.numCnfVariables(), inductstep.ez.numCnfClauses());
+ inductstep.ez->numCnfVariables(), inductstep.ez->numCnfClauses());
- if (!inductstep.solve(inductstep.ez.NOT(property))) {
+ if (!inductstep.solve(inductstep.ez->NOT(property))) {
if (inductstep.gotTimeout)
goto timeout;
log("Induction step proven: SUCCESS!\n");
}
log("Induction step failed. Incrementing induction length.\n");
- inductstep.ez.assume(property);
+ inductstep.ez->assume(property);
inductstep.print_model();
}
}
if (seq_len == 0) {
sathelper.setup();
if (sathelper.prove.size() || sathelper.prove_x.size() || sathelper.prove_asserts)
- sathelper.ez.assume(sathelper.ez.NOT(sathelper.setup_proof()));
+ sathelper.ez->assume(sathelper.ez->NOT(sathelper.setup_proof()));
} else {
std::vector<int> prove_bits;
for (int timestep = 1; timestep <= seq_len; timestep++) {
prove_bits.push_back(sathelper.setup_proof(timestep));
}
if (sathelper.prove.size() || sathelper.prove_x.size() || sathelper.prove_asserts)
- sathelper.ez.assume(sathelper.ez.NOT(sathelper.ez.expression(ezSAT::OpAnd, prove_bits)));
+ sathelper.ez->assume(sathelper.ez->NOT(sathelper.ez->expression(ezSAT::OpAnd, prove_bits)));
sathelper.setup_init();
}
sathelper.generate_model();
log("Dumping CNF to file `%s'.\n", cnf_file_name.c_str());
cnf_file_name.clear();
- sathelper.ez.printDIMACS(f, false);
+ sathelper.ez->printDIMACS(f, false);
fclose(f);
}
rerun_solver:
log("\nSolving problem with %d variables and %d clauses..\n",
- sathelper.ez.numCnfVariables(), sathelper.ez.numCnfClauses());
+ sathelper.ez->numCnfVariables(), sathelper.ez->numCnfClauses());
if (sathelper.solve())
{
module->fixup_ports();
Pass::call(design, "clean");
- ezDefaultSAT ez;
+ ezSatPtr ez;
SigMap sigmap(module);
- SatGen satgen(&ez, &sigmap);
+ SatGen satgen(ez.get(), &sigmap);
for (auto c : module->cells()) {
bool ok YS_ATTRIBUTE(unused) = satgen.importCell(c);
}
std::vector<int> in_vec = satgen.importSigSpec(in_sig);
- std::vector<int> inverse_in_vec = ez.vec_not(in_vec);
+ std::vector<int> inverse_in_vec = ez->vec_not(in_vec);
std::vector<int> out_vec = satgen.importSigSpec(out_sig);
assumptions.push_back((i & (1 << j)) ? in_vec.at(j) : inverse_in_vec.at(j));
std::vector<bool> results;
- if (!ez.solve(out_vec, results, assumptions)) {
+ if (!ez->solve(out_vec, results, assumptions)) {
log("No stable solution for input %d found -> recreate module.\n", i);
goto recreate_module;
}
for (int j = 0; j < 4; j++)
truthtab[i][j] = results[j];
- assumptions.push_back(ez.vec_ne(out_vec, ez.vec_const(results)));
+ assumptions.push_back(ez->vec_ne(out_vec, ez->vec_const(results)));
std::vector<bool> results2;
- if (ez.solve(out_vec, results2, assumptions)) {
+ if (ez->solve(out_vec, results2, assumptions)) {
log("Two stable solutions for input %d found -> recreate module.\n", i);
goto recreate_module;
}
log("\n");
log("Pre- and post-abc truth table:\n");
- ezDefaultSAT ez;
+ ezSatPtr ez;
SigMap sigmap(module);
- SatGen satgen(&ez, &sigmap);
+ SatGen satgen(ez.get(), &sigmap);
for (auto c : module->cells()) {
bool ok YS_ATTRIBUTE(unused) = satgen.importCell(c);
}
std::vector<int> in_vec = satgen.importSigSpec(in_sig);
- std::vector<int> inverse_in_vec = ez.vec_not(in_vec);
+ std::vector<int> inverse_in_vec = ez->vec_not(in_vec);
std::vector<int> out_vec = satgen.importSigSpec(out_sig);
truthtab2[i][j] = truthtab[i][j];
std::vector<bool> results;
- if (!ez.solve(out_vec, results, assumptions)) {
+ if (!ez->solve(out_vec, results, assumptions)) {
log("No stable solution for input %d found.\n", i);
found_error = true;
continue;
for (int j = 0; j < 4; j++)
truthtab2[i][j] = results[j];
- assumptions.push_back(ez.vec_ne(out_vec, ez.vec_const(results)));
+ assumptions.push_back(ez->vec_ne(out_vec, ez->vec_const(results)));
std::vector<bool> results2;
- if (ez.solve(out_vec, results2, assumptions)) {
+ if (ez->solve(out_vec, results2, assumptions)) {
log("Two stable solutions for input %d found -> recreate module.\n", i);
found_error = true;
}
RTLIL::Module *gate_mod = design->module("\\gate");
ConstEval gold_ce(gold_mod), gate_ce(gate_mod);
- ezDefaultSAT ez1, ez2;
+ ezSatPtr ez1, ez2;
SigMap sigmap(gold_mod);
- SatGen satgen1(&ez1, &sigmap);
- SatGen satgen2(&ez2, &sigmap);
+ SatGen satgen1(ez1.get(), &sigmap);
+ SatGen satgen2(ez2.get(), &sigmap);
satgen2.model_undef = true;
if (!nosat)
std::vector<int> sat1_model = satgen1.importSigSpec(out_sig);
std::vector<bool> sat1_model_value;
- if (!ez1.solve(sat1_model, sat1_model_value, ez1.vec_eq(sat1_in_sig, sat1_in_val)))
+ if (!ez1->solve(sat1_model, sat1_model_value, ez1->vec_eq(sat1_in_sig, sat1_in_val)))
log_error("Evaluating sat model 1 (no undef modeling) failed!\n");
if (verbose) {
std::vector<bool> sat2_model_value;
- if (!ez2.solve(sat2_model, sat2_model_value, ez2.vec_eq(sat2_in_def_sig, sat2_in_def_val), ez2.vec_eq(sat2_in_undef_sig, sat2_in_undef_val)))
+ if (!ez2->solve(sat2_model, sat2_model_value, ez2->vec_eq(sat2_in_def_sig, sat2_in_def_val), ez2->vec_eq(sat2_in_undef_sig, sat2_in_undef_val)))
log_error("Evaluating sat model 2 (undef modeling) failed!\n");
if (verbose) {