From: Clifford Wolf Date: Fri, 7 Jun 2013 12:37:33 +0000 (+0200) Subject: Improved sat generator and sat_solve pass X-Git-Tag: yosys-0.2.0~610 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=56b593b91cc693849e3b3b3de0666f6ec9a597f6;p=yosys.git Improved sat generator and sat_solve pass --- diff --git a/kernel/satgen.h b/kernel/satgen.h index 500c3f105..7535c7532 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -86,14 +86,6 @@ struct SatGen // cell_types.insert("$shr"); // cell_types.insert("$sshl"); // cell_types.insert("$sshr"); - // cell_types.insert("$lt"); - // cell_types.insert("$le"); - // cell_types.insert("$eq"); - // cell_types.insert("$ne"); - // cell_types.insert("$ge"); - // cell_types.insert("$gt"); - // cell_types.insert("$add"); - // cell_types.insert("$sub"); // cell_types.insert("$mul"); // cell_types.insert("$div"); // cell_types.insert("$mod"); @@ -104,19 +96,45 @@ struct SatGen // cell_types.insert("$pmux"); // cell_types.insert("$safe_pmux"); + void extendSignalWidth(std::vector &vec_a, std::vector &vec_b, RTLIL::Cell *cell) + { + bool is_signed_a = false, is_signed_b = false; + if (cell->parameters.count("\\A_SIGNED") > 0) + is_signed_a = cell->parameters["\\A_SIGNED"].as_bool(); + if (cell->parameters.count("\\B_SIGNED") > 0) + is_signed_b = cell->parameters["\\B_SIGNED"].as_bool(); + while (vec_a.size() < vec_b.size()) + vec_a.push_back(is_signed_a && vec_a.size() > 0 ? vec_a.back() : ez->FALSE); + while (vec_b.size() < vec_a.size()) + vec_b.push_back(is_signed_b && vec_b.size() > 0 ? vec_b.back() : ez->FALSE); + } + + void extendSignalWidth(std::vector &vec_a, std::vector &vec_b, std::vector &vec_y, RTLIL::Cell *cell) + { + extendSignalWidth(vec_a, vec_b, cell); + while (vec_y.size() < vec_a.size()) + vec_y.push_back(ez->literal()); + } + virtual void importCell(RTLIL::Cell *cell) { if (cell->type == "$_AND_" || cell->type == "$_OR_" || cell->type == "$_XOR_" || - cell->type == "$and" || cell->type == "$or" || cell->type == "$xor") { + cell->type == "$and" || cell->type == "$or" || cell->type == "$xor" || + cell->type == "$add" || cell->type == "$sub") { std::vector a = importSigSpec(cell->connections.at("\\A")); std::vector b = importSigSpec(cell->connections.at("\\B")); std::vector y = importSigSpec(cell->connections.at("\\Y")); + extendSignalWidth(a, b, y, cell); if (cell->type == "$and" || cell->type == "$_AND_") ez->assume(ez->vec_eq(ez->vec_and(a, b), y)); if (cell->type == "$or" || cell->type == "$_OR_") ez->assume(ez->vec_eq(ez->vec_or(a, b), y)); if (cell->type == "$xor" || cell->type == "$_XOR") ez->assume(ez->vec_eq(ez->vec_xor(a, b), y)); + if (cell->type == "$add") + ez->assume(ez->vec_eq(ez->vec_add(a, b), y)); + if (cell->type == "$sub") + ez->assume(ez->vec_eq(ez->vec_sub(a, b), y)); } else if (cell->type == "$_INV_" || cell->type == "$not") { std::vector a = importSigSpec(cell->connections.at("\\A")); @@ -129,6 +147,25 @@ struct SatGen std::vector s = importSigSpec(cell->connections.at("\\S")); std::vector y = importSigSpec(cell->connections.at("\\Y")); ez->assume(ez->vec_eq(ez->vec_ite(s, b, a), y)); + } else + if (cell->type == "$lt" || cell->type == "$le" || cell->type == "$eq" || cell->type == "$ne" || cell->type == "$ge" || cell->type == "$gt") { + bool is_signed = cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool(); + std::vector a = importSigSpec(cell->connections.at("\\A")); + std::vector b = importSigSpec(cell->connections.at("\\B")); + std::vector y = importSigSpec(cell->connections.at("\\Y")); + extendSignalWidth(a, b, cell); + if (cell->type == "$lt") + ez->SET(is_signed ? ez->vec_lt_signed(a, b) : ez->vec_lt_unsigned(a, b), y.at(0)); + if (cell->type == "$le") + ez->SET(is_signed ? ez->vec_le_signed(a, b) : ez->vec_le_unsigned(a, b), y.at(0)); + if (cell->type == "$eq") + ez->SET(ez->vec_eq(a, b), y.at(0)); + if (cell->type == "$ne") + ez->SET(ez->vec_ne(a, b), y.at(0)); + if (cell->type == "$ge") + ez->SET(is_signed ? ez->vec_ge_signed(a, b) : ez->vec_ge_unsigned(a, b), y.at(0)); + if (cell->type == "$gt") + ez->SET(is_signed ? ez->vec_gt_signed(a, b) : ez->vec_gt_unsigned(a, b), y.at(0)); } else log_error("Can't handle cell type %s in SAT generator yet.\n", RTLIL::id2cstr(cell->type)); } diff --git a/libs/ezsat/ezsat.cc b/libs/ezsat/ezsat.cc index d6ebd678b..cf9dd65b9 100644 --- a/libs/ezsat/ezsat.cc +++ b/libs/ezsat/ezsat.cc @@ -34,6 +34,7 @@ ezSAT::ezSAT() cnfConsumed = false; cnfVariableCount = 0; + cnfClausesCount = 0; } ezSAT::~ezSAT() @@ -331,6 +332,7 @@ void ezSAT::clear() { cnfConsumed = false; cnfVariableCount = 0; + cnfClausesCount = 0; cnfLiteralVariables.clear(); cnfExpressionVariables.clear(); cnfClauses.clear(); @@ -342,11 +344,13 @@ void ezSAT::assume(int id) int idx = bind(id); cnfClauses.push_back(std::vector(1, idx)); cnfAssumptions.insert(id); + cnfClausesCount++; } void ezSAT::add_clause(const std::vector &args) { cnfClauses.push_back(args); + cnfClausesCount++; } void ezSAT::add_clause(const std::vector &args, bool argsPolarity, int a, int b, int c) diff --git a/libs/ezsat/ezsat.h b/libs/ezsat/ezsat.h index 29b7aca71..ea873a859 100644 --- a/libs/ezsat/ezsat.h +++ b/libs/ezsat/ezsat.h @@ -55,7 +55,7 @@ private: std::vector>> expressions; bool cnfConsumed; - int cnfVariableCount; + int cnfVariableCount, cnfClausesCount; std::vector cnfLiteralVariables, cnfExpressionVariables; std::vector> cnfClauses; std::set cnfAssumptions; @@ -137,6 +137,7 @@ public: int bound(int id) const; int numCnfVariables() const { return cnfVariableCount; } + int numCnfClauses() const { return cnfClausesCount; } const std::vector> &cnf() const { return cnfClauses; } void consumeCnf(); diff --git a/libs/ezsat/puzzle3d.cc b/libs/ezsat/puzzle3d.cc index 1655e6972..56d293260 100644 --- a/libs/ezsat/puzzle3d.cc +++ b/libs/ezsat/puzzle3d.cc @@ -255,7 +255,7 @@ int main() ez.assume(ez.ordered(vecvec[0], vecvec[1])); printf("Found and eliminated %d spatial symmetries.\n", int(symmetries.size())); - printf("Generated %d clauses over %d variables.\n", ez.numCnfVariables(), int(ez.cnf().size())); + printf("Generated %d clauses over %d variables.\n", ez.numCnfClauses(), ez.numCnfVariables()); std::vector modelExpressions; std::vector modelValues; diff --git a/passes/sat/example.ys b/passes/sat/example.ys index b7798ab2e..e2eb17497 100644 --- a/passes/sat/example.ys +++ b/passes/sat/example.ys @@ -1,3 +1,3 @@ read_verilog example.v -techmap; opt +techmap; opt; abc; opt sat_solve -show a -set y 1'b1 diff --git a/passes/sat/sat_solve.cc b/passes/sat/sat_solve.cc index 1644eaaa1..0f826fc94 100644 --- a/passes/sat/sat_solve.cc +++ b/passes/sat/sat_solve.cc @@ -129,7 +129,7 @@ struct SatSolvePass : public Pass { std::vector> sets; std::vector shows; - log_header("Executing SAT_SOLVE pass (detecting logic loops).\n"); + log_header("Executing SAT_SOLVE pass (solving SAT problems in the circuit).\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -189,7 +189,7 @@ struct SatSolvePass : public Pass { satgen.importCell(c.second); import_cell_counter++; } - log("Imported %d cells.\n", import_cell_counter); + log("Imported %d cells to SAT database.\n", import_cell_counter); std::vector modelExpressions; std::vector modelValues; @@ -227,7 +227,7 @@ struct SatSolvePass : public Pass { } } - log("Solving problem with %d variables and %d clauses..\n", ez.numCnfVariables(), int(ez.cnf().size())); + log("Solving problem with %d variables and %d clauses..\n", ez.numCnfVariables(), ez.numCnfClauses()); if (ez.solve(modelExpressions, modelValues)) { log("SAT solving finished - model found:\n");