Various equiv_simple improvements

This commit is contained in:
Clifford Wolf 2015-01-22 13:40:26 +01:00
parent 0a225f8b27
commit a6aa32e762
2 changed files with 69 additions and 25 deletions

View File

@ -1163,6 +1163,25 @@ struct SatGen
return true; return true;
} }
if (cell->type == "$_BUF_" || cell->type == "$equiv")
{
std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
extendSignalWidthUnary(a, y, cell);
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
ez->assume(ez->vec_eq(a, yy));
if (model_undef) {
std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
extendSignalWidthUnary(undef_a, undef_y, cell, false);
ez->assume(ez->vec_eq(undef_a, undef_y));
undefGating(y, yy, undef_y);
}
return true;
}
if (cell->type == "$assert") if (cell->type == "$assert")
{ {
std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep)); std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));

View File

@ -34,10 +34,11 @@ struct EquivSimpleWorker
ezDefaultSAT ez; ezDefaultSAT ez;
SatGen satgen; SatGen satgen;
int max_seq; int max_seq;
bool verbose;
EquivSimpleWorker(Cell *equiv_cell, SigMap &sigmap, dict<SigBit, Cell*> &bit2driver, int max_seq) : EquivSimpleWorker(Cell *equiv_cell, SigMap &sigmap, dict<SigBit, Cell*> &bit2driver, int max_seq, bool verbose) :
module(equiv_cell->module), equiv_cell(equiv_cell), sigmap(sigmap), module(equiv_cell->module), equiv_cell(equiv_cell), sigmap(sigmap),
bit2driver(bit2driver), satgen(&ez, &sigmap), max_seq(max_seq) bit2driver(bit2driver), satgen(&ez, &sigmap), max_seq(max_seq), verbose(verbose)
{ {
} }
@ -90,8 +91,12 @@ struct EquivSimpleWorker
pool<SigBit> seed_a = { bit_a }; pool<SigBit> seed_a = { bit_a };
pool<SigBit> seed_b = { bit_b }; pool<SigBit> seed_b = { bit_b };
log(" Trying to prove $equiv cell %s:\n", log_id(equiv_cell)); if (verbose) {
log(" A = %s, B = %s, Y = %s\n", log_signal(bit_a), log_signal(bit_b), log_signal(equiv_cell->getPort("\\Y"))); log(" Trying to prove $equiv cell %s:\n", log_id(equiv_cell));
log(" A = %s, B = %s, Y = %s\n", log_signal(bit_a), log_signal(bit_b), log_signal(equiv_cell->getPort("\\Y")));
} else {
log(" Trying to prove $equiv for %s:", log_signal(equiv_cell->getPort("\\Y")));
}
int step = max_seq; int step = max_seq;
while (1) while (1)
@ -127,54 +132,66 @@ struct EquivSimpleWorker
problem_cells.insert(short_cells_cone_a.begin(), short_cells_cone_a.end()); problem_cells.insert(short_cells_cone_a.begin(), short_cells_cone_a.end());
problem_cells.insert(short_cells_cone_b.begin(), short_cells_cone_b.end()); problem_cells.insert(short_cells_cone_b.begin(), short_cells_cone_b.end());
log(" Adding %d new cells to the problem (%d A, %d B, %d shared).\n", if (verbose)
GetSize(problem_cells), GetSize(short_cells_cone_a), GetSize(short_cells_cone_b), log(" Adding %d new cells to the problem (%d A, %d B, %d shared).\n",
(GetSize(short_cells_cone_a) + GetSize(short_cells_cone_b)) - GetSize(problem_cells)); GetSize(problem_cells), GetSize(short_cells_cone_a), GetSize(short_cells_cone_b),
(GetSize(short_cells_cone_a) + GetSize(short_cells_cone_b)) - GetSize(problem_cells));
for (auto cell : problem_cells) for (auto cell : problem_cells)
satgen.importCell(cell, step+1); if (!satgen.importCell(cell, step+1))
log_cmd_error("No SAT model available for cell %s (%s).\n", log_id(cell), log_id(cell->type));
log(" Problem size at t=%d: %d literals, %d clauses\n", step, ez.numCnfVariables(), ez.numCnfClauses()); if (verbose)
log(" Problem size at t=%d: %d literals, %d clauses\n", step, ez.numCnfVariables(), ez.numCnfClauses());
if (!ez.solve()) { if (!ez.solve()) {
log(" Proved equivalence! Marking $equiv cell as proven.\n"); log(verbose ? " Proved equivalence! Marking $equiv cell as proven.\n" : " success!\n");
equiv_cell->setPort("\\B", equiv_cell->getPort("\\A")); equiv_cell->setPort("\\B", equiv_cell->getPort("\\A"));
return true; return true;
} }
log(" Failed to prove equivalence with sequence length %d.\n", max_seq - step); if (verbose)
log(" Failed to prove equivalence with sequence length %d.\n", max_seq - step);
if (--step < 0) { if (--step < 0) {
log(" Reached sequence limit.\n"); if (verbose)
log(" Reached sequence limit.\n");
break; break;
} }
if (seed_a.empty() && seed_b.empty()) { if (seed_a.empty() && seed_b.empty()) {
log(" No nets to continue in previous time step.\n"); if (verbose)
log(" No nets to continue in previous time step.\n");
break; break;
} }
if (seed_a.empty()) { if (seed_a.empty()) {
log(" No nets on A-side to continue in previous time step.\n"); if (verbose)
log(" No nets on A-side to continue in previous time step.\n");
break; break;
} }
if (seed_b.empty()) { if (seed_b.empty()) {
log(" No nets on B-side to continue in previous time step.\n"); if (verbose)
log(" No nets on B-side to continue in previous time step.\n");
break; break;
} }
#if 0 if (verbose) {
log(" Continuing analysis in previous time step with the following nets:\n"); #if 0
for (auto bit : seed_a) log(" Continuing analysis in previous time step with the following nets:\n");
log(" A: %s\n", log_signal(bit)); for (auto bit : seed_a)
for (auto bit : seed_b) log(" A: %s\n", log_signal(bit));
log(" B: %s\n", log_signal(bit)); for (auto bit : seed_b)
#else log(" B: %s\n", log_signal(bit));
log(" Continuing analysis in previous time step with %d A- and %d B-nets.\n", GetSize(seed_a), GetSize(seed_b)); #else
#endif log(" Continuing analysis in previous time step with %d A- and %d B-nets.\n", GetSize(seed_a), GetSize(seed_b));
#endif
}
} }
if (!verbose)
log(" failed.\n");
return false; return false;
} }
}; };
@ -189,12 +206,16 @@ struct EquivSimplePass : public Pass {
log("\n"); log("\n");
log("This command tries to prove $equiv cells using a simple direct SAT approach.\n"); log("This command tries to prove $equiv cells using a simple direct SAT approach.\n");
log("\n"); log("\n");
log(" -v\n");
log(" verbose output\n");
log("\n");
log(" -seq <N>\n"); log(" -seq <N>\n");
log(" the max. number of time steps to be considered (default = 1)\n"); log(" the max. number of time steps to be considered (default = 1)\n");
log("\n"); log("\n");
} }
virtual void execute(std::vector<std::string> args, Design *design) virtual void execute(std::vector<std::string> args, Design *design)
{ {
bool verbose = false;
int success_counter = 0; int success_counter = 0;
int max_seq = 1; int max_seq = 1;
@ -202,6 +223,10 @@ struct EquivSimplePass : public Pass {
size_t argidx; size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) { for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-v") {
verbose = true;
continue;
}
if (args[argidx] == "-seq" && argidx+1 < args.size()) { if (args[argidx] == "-seq" && argidx+1 < args.size()) {
max_seq = atoi(args[++argidx].c_str()); max_seq = atoi(args[++argidx].c_str());
continue; continue;
@ -240,7 +265,7 @@ struct EquivSimplePass : public Pass {
} }
for (auto cell : unproven_equiv_cells) { for (auto cell : unproven_equiv_cells) {
EquivSimpleWorker worker(cell, sigmap, bit2driver, max_seq); EquivSimpleWorker worker(cell, sigmap, bit2driver, max_seq, verbose);
if (worker.run()) if (worker.run())
success_counter++; success_counter++;
} }