946 std::vector<std::pair<std::string, std::string>> sets, sets_init, prove, prove_x;
947 std::map<int, std::vector<std::pair<std::string, std::string>>> sets_at;
948 std::map<int, std::vector<std::string>> unsets_at, sets_def_at, sets_any_undef_at, sets_all_undef_at;
949 std::vector<std::string> shows, sets_def, sets_any_undef, sets_all_undef;
950 int loopcount = 0, seq_len = 0, maxsteps = 0, initsteps = 0, timeout = 0, prove_skip = 0;
951 bool verify =
false, fail_on_timeout =
false, enable_undef =
false, set_def_inputs =
false;
952 bool ignore_div_by_zero =
false, set_init_undef =
false, set_init_zero =
false, max_undef =
false;
953 bool tempinduct =
false, prove_asserts =
false, show_inputs =
false, show_outputs =
false;
954 bool ignore_unknown_cells =
false, falsify =
false, tempinduct_def =
false, set_init_def =
false;
955 std::string vcd_file_name, cnf_file_name;
957 log_header(
"Executing SAT pass (solving SAT problems in the circuit).\n");
960 for (argidx = 1; argidx <
args.size(); argidx++) {
961 if (
args[argidx] ==
"-all") {
965 if (
args[argidx] ==
"-verify") {
966 fail_on_timeout =
true;
970 if (
args[argidx] ==
"-verify-no-timeout") {
974 if (
args[argidx] ==
"-falsify") {
975 fail_on_timeout =
true;
979 if (
args[argidx] ==
"-falsify-no-timeout") {
983 if (
args[argidx] ==
"-timeout" && argidx+1 <
args.size()) {
984 timeout = atoi(
args[++argidx].c_str());
987 if (
args[argidx] ==
"-max" && argidx+1 <
args.size()) {
988 loopcount = atoi(
args[++argidx].c_str());
991 if (
args[argidx] ==
"-maxsteps" && argidx+1 <
args.size()) {
992 maxsteps = atoi(
args[++argidx].c_str());
995 if (
args[argidx] ==
"-initsteps" && argidx+1 <
args.size()) {
996 initsteps = atoi(
args[++argidx].c_str());
999 if (
args[argidx] ==
"-ignore_div_by_zero") {
1000 ignore_div_by_zero =
true;
1003 if (
args[argidx] ==
"-enable_undef") {
1004 enable_undef =
true;
1007 if (
args[argidx] ==
"-max_undef") {
1008 enable_undef =
true;
1012 if (
args[argidx] ==
"-set-def-inputs") {
1013 enable_undef =
true;
1014 set_def_inputs =
true;
1017 if (
args[argidx] ==
"-set" && argidx+2 <
args.size()) {
1018 std::string lhs =
args[++argidx];
1019 std::string rhs =
args[++argidx];
1020 sets.push_back(std::pair<std::string, std::string>(lhs, rhs));
1023 if (
args[argidx] ==
"-set-def" && argidx+1 <
args.size()) {
1024 sets_def.push_back(
args[++argidx]);
1025 enable_undef =
true;
1028 if (
args[argidx] ==
"-set-any-undef" && argidx+1 <
args.size()) {
1029 sets_any_undef.push_back(
args[++argidx]);
1030 enable_undef =
true;
1033 if (
args[argidx] ==
"-set-all-undef" && argidx+1 <
args.size()) {
1034 sets_all_undef.push_back(
args[++argidx]);
1035 enable_undef =
true;
1038 if (
args[argidx] ==
"-tempinduct") {
1042 if (
args[argidx] ==
"-tempinduct-def") {
1044 tempinduct_def =
true;
1047 if (
args[argidx] ==
"-prove" && argidx+2 <
args.size()) {
1048 std::string lhs =
args[++argidx];
1049 std::string rhs =
args[++argidx];
1050 prove.push_back(std::pair<std::string, std::string>(lhs, rhs));
1053 if (
args[argidx] ==
"-prove-x" && argidx+2 <
args.size()) {
1054 std::string lhs =
args[++argidx];
1055 std::string rhs =
args[++argidx];
1056 prove_x.push_back(std::pair<std::string, std::string>(lhs, rhs));
1057 enable_undef =
true;
1060 if (
args[argidx] ==
"-prove-asserts") {
1061 prove_asserts =
true;
1064 if (
args[argidx] ==
"-prove-skip" && argidx+1 <
args.size()) {
1065 prove_skip = atoi(
args[++argidx].c_str());
1068 if (
args[argidx] ==
"-seq" && argidx+1 <
args.size()) {
1069 seq_len = atoi(
args[++argidx].c_str());
1072 if (
args[argidx] ==
"-set-at" && argidx+3 <
args.size()) {
1073 int timestep = atoi(
args[++argidx].c_str());
1074 std::string lhs =
args[++argidx];
1075 std::string rhs =
args[++argidx];
1076 sets_at[timestep].push_back(std::pair<std::string, std::string>(lhs, rhs));
1079 if (
args[argidx] ==
"-unset-at" && argidx+2 <
args.size()) {
1080 int timestep = atoi(
args[++argidx].c_str());
1081 unsets_at[timestep].push_back(
args[++argidx]);
1084 if (
args[argidx] ==
"-set-def-at" && argidx+2 <
args.size()) {
1085 int timestep = atoi(
args[++argidx].c_str());
1086 sets_def_at[timestep].push_back(
args[++argidx]);
1087 enable_undef =
true;
1090 if (
args[argidx] ==
"-set-any-undef-at" && argidx+2 <
args.size()) {
1091 int timestep = atoi(
args[++argidx].c_str());
1092 sets_any_undef_at[timestep].push_back(
args[++argidx]);
1093 enable_undef =
true;
1096 if (
args[argidx] ==
"-set-all-undef-at" && argidx+2 <
args.size()) {
1097 int timestep = atoi(
args[++argidx].c_str());
1098 sets_all_undef_at[timestep].push_back(
args[++argidx]);
1099 enable_undef =
true;
1102 if (
args[argidx] ==
"-set-init" && argidx+2 <
args.size()) {
1103 std::string lhs =
args[++argidx];
1104 std::string rhs =
args[++argidx];
1105 sets_init.push_back(std::pair<std::string, std::string>(lhs, rhs));
1108 if (
args[argidx] ==
"-set-init-undef") {
1109 set_init_undef =
true;
1110 enable_undef =
true;
1113 if (
args[argidx] ==
"-set-init-def") {
1114 set_init_def =
true;
1117 if (
args[argidx] ==
"-set-init-zero") {
1118 set_init_zero =
true;
1121 if (
args[argidx] ==
"-show" && argidx+1 <
args.size()) {
1122 shows.push_back(
args[++argidx]);
1125 if (
args[argidx] ==
"-show-inputs") {
1129 if (
args[argidx] ==
"-show-outputs") {
1130 show_outputs =
true;
1133 if (
args[argidx] ==
"-ignore_unknown_cells") {
1134 ignore_unknown_cells =
true;
1137 if (
args[argidx] ==
"-dump_vcd" && argidx+1 <
args.size()) {
1138 vcd_file_name =
args[++argidx];
1141 if (
args[argidx] ==
"-dump_cnf" && argidx+1 <
args.size()) {
1142 cnf_file_name =
args[++argidx];
1150 for (
auto &mod_it : design->
modules_)
1151 if (design->
selected(mod_it.second)) {
1153 log_cmd_error(
"Only one module must be selected for the SAT pass! (selected: %s and %s)\n",
1155 module = mod_it.second;
1158 log_cmd_error(
"Can't perform SAT on an empty selection!\n");
1160 if (!prove.size() && !prove_x.size() && !prove_asserts && tempinduct)
1163 if (prove_skip && tempinduct)
1164 log_cmd_error(
"Options -prove-skip and -tempinduct don't work with each other.\n");
1166 if (prove_skip >= seq_len && prove_skip > 0)
1167 log_cmd_error(
"The value of -prove-skip must be smaller than the one of -seq.\n");
1169 if (set_init_undef + set_init_zero + set_init_def > 1)
1170 log_cmd_error(
"The options -set-init-undef, -set-init-def, and -set-init-zero are exclusive!\n");
1172 if (set_def_inputs) {
1173 for (
auto &it : module->
wires_)
1174 if (it.second->port_input)
1175 sets_def.push_back(it.second->name.str());
1179 for (
auto &it : module->
wires_)
1180 if (it.second->port_input)
1181 shows.push_back(it.second->name.str());
1185 for (
auto &it : module->
wires_)
1186 if (it.second->port_output)
1187 shows.push_back(it.second->name.str());
1192 if (loopcount > 0 || max_undef)
1193 log_cmd_error(
"The options -max, -all, and -max_undef are not supported for temporal induction proofs!\n");
1195 SatHelper basecase(design, module, enable_undef);
1196 SatHelper inductstep(design, module, enable_undef);
1198 basecase.sets = sets;
1199 basecase.prove = prove;
1200 basecase.prove_x = prove_x;
1201 basecase.prove_asserts = prove_asserts;
1202 basecase.sets_at = sets_at;
1203 basecase.unsets_at = unsets_at;
1204 basecase.shows = shows;
1205 basecase.timeout = timeout;
1206 basecase.sets_def = sets_def;
1207 basecase.sets_any_undef = sets_any_undef;
1208 basecase.sets_all_undef = sets_all_undef;
1209 basecase.sets_def_at = sets_def_at;
1210 basecase.sets_any_undef_at = sets_any_undef_at;
1211 basecase.sets_all_undef_at = sets_all_undef_at;
1212 basecase.sets_init = sets_init;
1213 basecase.set_init_def = set_init_def;
1214 basecase.set_init_undef = set_init_undef;
1215 basecase.set_init_zero = set_init_zero;
1216 basecase.satgen.ignore_div_by_zero = ignore_div_by_zero;
1217 basecase.ignore_unknown_cells = ignore_unknown_cells;
1219 for (
int timestep = 1; timestep <= seq_len; timestep++)
1220 basecase.setup(timestep);
1221 basecase.setup_init();
1223 inductstep.sets = sets;
1224 inductstep.prove = prove;
1225 inductstep.prove_x = prove_x;
1226 inductstep.prove_asserts = prove_asserts;
1227 inductstep.shows = shows;
1228 inductstep.timeout = timeout;
1229 inductstep.sets_def = sets_def;
1230 inductstep.sets_any_undef = sets_any_undef;
1231 inductstep.sets_all_undef = sets_all_undef;
1232 inductstep.satgen.ignore_div_by_zero = ignore_div_by_zero;
1233 inductstep.ignore_unknown_cells = ignore_unknown_cells;
1235 inductstep.setup(1);
1236 inductstep.ez.assume(inductstep.setup_proof(1));
1238 if (tempinduct_def) {
1239 std::vector<int> undef_state = inductstep.satgen.importUndefSigSpec(inductstep.satgen.initial_state.export_all(), 1);
1240 inductstep.ez.assume(inductstep.ez.NOT(inductstep.ez.expression(
ezSAT::OpOr, undef_state)));
1243 for (
int inductlen = 1; inductlen <= maxsteps || maxsteps == 0; inductlen++)
1245 log(
"\n** Trying induction with length %d **\n", inductlen);
1249 basecase.setup(seq_len + inductlen);
1250 int property = basecase.setup_proof(seq_len + inductlen);
1251 basecase.generate_model();
1254 basecase.force_unique_state(seq_len + 1, seq_len + inductlen);
1256 log(
"\n[base case] Solving problem with %d variables and %d clauses..\n",
1257 basecase.ez.numCnfVariables(), basecase.ez.numCnfClauses());
1259 if (basecase.solve(basecase.ez.NOT(property))) {
1260 log(
"SAT temporal induction proof finished - model found for base case: FAIL!\n");
1262 basecase.print_model();
1263 if(!vcd_file_name.empty())
1264 basecase.dump_model_to_vcd(vcd_file_name);
1268 if (basecase.gotTimeout)
1271 log(
"Base case for induction length %d proven.\n", inductlen);
1272 basecase.ez.assume(property);
1276 inductstep.setup(inductlen + 1);
1277 property = inductstep.setup_proof(inductlen + 1);
1278 inductstep.generate_model();
1281 inductstep.force_unique_state(1, inductlen + 1);
1283 if (inductlen < initsteps)
1285 log(
"\n[induction step] Skipping problem with %d variables and %d clauses (below initsteps).\n",
1286 inductstep.ez.numCnfVariables(), inductstep.ez.numCnfClauses());
1287 inductstep.ez.assume(property);
1291 if (!cnf_file_name.empty())
1293 FILE *f = fopen(cnf_file_name.c_str(),
"w");
1295 log_cmd_error(
"Can't open output file `%s' for writing: %s\n", cnf_file_name.c_str(), strerror(errno));
1297 log(
"Dumping CNF to file `%s'.\n", cnf_file_name.c_str());
1298 cnf_file_name.clear();
1300 inductstep.ez.printDIMACS(f,
false);
1304 log(
"\n[induction step] Solving problem with %d variables and %d clauses..\n",
1305 inductstep.ez.numCnfVariables(), inductstep.ez.numCnfClauses());
1307 if (!inductstep.solve(inductstep.ez.NOT(property))) {
1308 if (inductstep.gotTimeout)
1310 log(
"Induction step proven: SUCCESS!\n");
1315 log(
"Induction step failed. Incrementing induction length.\n");
1316 inductstep.ez.assume(property);
1317 inductstep.print_model();
1321 log(
"\nReached maximum number of time steps -> proof failed.\n");
1322 if(!vcd_file_name.empty())
1323 inductstep.dump_model_to_vcd(vcd_file_name);
1329 log_error(
"Called with -verify and proof did fail!\n");
1336 log_error(
"Called with -falsify and proof did succeed!\n");
1342 log_cmd_error(
"The options -maxsteps is only supported for temporal induction proofs!\n");
1344 SatHelper sathelper(design, module, enable_undef);
1346 sathelper.sets = sets;
1347 sathelper.prove = prove;
1348 sathelper.prove_x = prove_x;
1349 sathelper.prove_asserts = prove_asserts;
1350 sathelper.sets_at = sets_at;
1351 sathelper.unsets_at = unsets_at;
1352 sathelper.shows = shows;
1353 sathelper.timeout = timeout;
1354 sathelper.sets_def = sets_def;
1355 sathelper.sets_any_undef = sets_any_undef;
1356 sathelper.sets_all_undef = sets_all_undef;
1357 sathelper.sets_def_at = sets_def_at;
1358 sathelper.sets_any_undef_at = sets_any_undef_at;
1359 sathelper.sets_all_undef_at = sets_all_undef_at;
1360 sathelper.sets_init = sets_init;
1361 sathelper.set_init_def = set_init_def;
1362 sathelper.set_init_undef = set_init_undef;
1363 sathelper.set_init_zero = set_init_zero;
1364 sathelper.satgen.ignore_div_by_zero = ignore_div_by_zero;
1365 sathelper.ignore_unknown_cells = ignore_unknown_cells;
1369 if (sathelper.prove.size() || sathelper.prove_x.size() || sathelper.prove_asserts)
1370 sathelper.ez.assume(sathelper.ez.NOT(sathelper.setup_proof()));
1372 std::vector<int> prove_bits;
1373 for (
int timestep = 1; timestep <= seq_len; timestep++) {
1374 sathelper.setup(timestep);
1375 if (sathelper.prove.size() || sathelper.prove_x.size() || sathelper.prove_asserts)
1376 if (timestep > prove_skip)
1377 prove_bits.push_back(sathelper.setup_proof(timestep));
1379 if (sathelper.prove.size() || sathelper.prove_x.size() || sathelper.prove_asserts)
1380 sathelper.ez.assume(sathelper.ez.NOT(sathelper.ez.expression(
ezSAT::OpAnd, prove_bits)));
1381 sathelper.setup_init();
1383 sathelper.generate_model();
1385 if (!cnf_file_name.empty())
1387 FILE *f = fopen(cnf_file_name.c_str(),
"w");
1389 log_cmd_error(
"Can't open output file `%s' for writing: %s\n", cnf_file_name.c_str(), strerror(errno));
1391 log(
"Dumping CNF to file `%s'.\n", cnf_file_name.c_str());
1392 cnf_file_name.clear();
1394 sathelper.ez.printDIMACS(f,
false);
1398 int rerun_counter = 0;
1401 log(
"\nSolving problem with %d variables and %d clauses..\n",
1402 sathelper.ez.numCnfVariables(), sathelper.ez.numCnfClauses());
1404 if (sathelper.solve())
1407 log(
"SAT model found. maximizing number of undefs.\n");
1408 sathelper.maximize_undefs();
1411 if (!prove.size() && !prove_x.size() && !prove_asserts) {
1412 log(
"SAT solving finished - model found:\n");
1414 log(
"SAT proof finished - model found: FAIL!\n");
1418 sathelper.print_model();
1420 if(!vcd_file_name.empty())
1421 sathelper.dump_model_to_vcd(vcd_file_name);
1423 if (loopcount != 0) {
1424 loopcount--, rerun_counter++;
1425 sathelper.invalidate_model(max_undef);
1429 if (!prove.size() && !prove_x.size() && !prove_asserts) {
1432 log_error(
"Called with -falsify and found a model!\n");
1437 log_error(
"Called with -verify and proof did fail!\n");
1443 if (sathelper.gotTimeout)
1446 log(
"SAT solving finished - no more models found (after %d distinct solutions).\n", rerun_counter);
1447 else if (!prove.size() && !prove_x.size() && !prove_asserts) {
1448 log(
"SAT solving finished - no model found.\n");
1451 log_error(
"Called with -verify and found no model!\n");
1454 log(
"SAT proof finished - no model found: SUCCESS!\n");
1458 log_error(
"Called with -falsify and proof did succeed!\n");
1463 if (!prove.size() && !prove_x.size() && !prove_asserts) {
1464 if (falsify && rerun_counter) {
1466 log_error(
"Called with -falsify and found a model!\n");
1469 if (verify && rerun_counter) {
1471 log_error(
"Called with -verify and proof did fail!\n");
1478 log(
"Interrupted SAT solver: TIMEOUT!\n");
1480 if (fail_on_timeout)
1481 log_error(
"Called with -verify and proof did time out!\n");
bool selected(T1 *module) const
void print_proof_failed()
void log_header(const char *format,...)
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
void log_error(const char *format,...)
static const char * id2cstr(const RTLIL::IdString &str)
void log_cmd_error(const char *format,...)
std::map< RTLIL::IdString, RTLIL::Module * > modules_
void log(const char *format,...)
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)