yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
sat.cc
Go to the documentation of this file.
1 /*
2  * yosys -- Yosys Open SYnthesis Suite
3  *
4  * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  */
19 
20 // [[CITE]] Temporal Induction by Incremental SAT Solving
21 // Niklas Een and Niklas Sörensson (2003)
22 // http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.8161
23 
24 #include "kernel/register.h"
25 #include "kernel/celltypes.h"
26 #include "kernel/consteval.h"
27 #include "kernel/sigtools.h"
28 #include "kernel/log.h"
29 #include "kernel/satgen.h"
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <algorithm>
33 #include <errno.h>
34 #include <string.h>
35 
38 
39 struct SatHelper
40 {
43 
48 
49  // additional constraints
50  std::vector<std::pair<std::string, std::string>> sets, prove, prove_x, sets_init;
51  std::map<int, std::vector<std::pair<std::string, std::string>>> sets_at;
52  std::map<int, std::vector<std::string>> unsets_at;
54 
55  // undef constraints
57  std::vector<std::string> sets_def, sets_any_undef, sets_all_undef;
58  std::map<int, std::vector<std::string>> sets_def_at, sets_any_undef_at, sets_all_undef_at;
59 
60  // model variables
61  std::vector<std::string> shows;
65  bool gotTimeout;
66 
68  design(design), module(module), sigmap(module), ct(design), satgen(&ez, &sigmap)
69  {
70  this->enable_undef = enable_undef;
72  set_init_def = false;
73  set_init_undef = false;
74  set_init_zero = false;
75  ignore_unknown_cells = false;
76  max_timestep = -1;
77  timeout = 0;
78  gotTimeout = false;
79  }
80 
82  {
83  if (enable_undef)
84  return;
85 
86  std::vector<RTLIL::SigBit> sigbits = sig.to_sigbit_vector();
87  for (size_t i = 0; i < sigbits.size(); i++)
88  if (sigbits[i].wire == NULL && sigbits[i].data == RTLIL::State::Sx)
89  log_cmd_error("Bit %d of %s is undef but option -enable_undef is missing!\n", int(i), log_signal(sig));
90  }
91 
92  void setup_init()
93  {
94  log ("\nSetting up initial state:\n");
95 
96  RTLIL::SigSpec big_lhs, big_rhs;
97 
98  for (auto &it : module->wires_)
99  {
100  if (it.second->attributes.count("\\init") == 0)
101  continue;
102 
103  RTLIL::SigSpec lhs = sigmap(it.second);
104  RTLIL::SigSpec rhs = it.second->attributes.at("\\init");
105  log_assert(lhs.size() == rhs.size());
106 
107  RTLIL::SigSpec removed_bits;
108  for (int i = 0; i < lhs.size(); i++) {
109  RTLIL::SigSpec bit = lhs.extract(i, 1);
110  if (!satgen.initial_state.check_all(bit)) {
111  removed_bits.append(bit);
112  lhs.remove(i, 1);
113  rhs.remove(i, 1);
114  i--;
115  }
116  }
117 
118  if (removed_bits.size())
119  log_warning("ignoring initial value on non-register: %s\n", log_signal(removed_bits));
120 
121  if (lhs.size()) {
122  log("Import set-constraint from init attribute: %s = %s\n", log_signal(lhs), log_signal(rhs));
123  big_lhs.remove2(lhs, &big_rhs);
124  big_lhs.append(lhs);
125  big_rhs.append(rhs);
126  }
127  }
128 
129  for (auto &s : sets_init)
130  {
131  RTLIL::SigSpec lhs, rhs;
132 
133  if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s.first))
134  log_cmd_error("Failed to parse lhs set expression `%s'.\n", s.first.c_str());
135  if (!RTLIL::SigSpec::parse_rhs(lhs, rhs, module, s.second))
136  log_cmd_error("Failed to parse rhs set expression `%s'.\n", s.second.c_str());
139 
140  if (lhs.size() != rhs.size())
141  log_cmd_error("Set expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
142  s.first.c_str(), log_signal(lhs), lhs.size(), s.second.c_str(), log_signal(rhs), rhs.size());
143 
144  log("Import set-constraint: %s = %s\n", log_signal(lhs), log_signal(rhs));
145  big_lhs.remove2(lhs, &big_rhs);
146  big_lhs.append(lhs);
147  big_rhs.append(rhs);
148  }
149 
150  if (!satgen.initial_state.check_all(big_lhs)) {
151  RTLIL::SigSpec rem = satgen.initial_state.remove(big_lhs);
152  log_cmd_error("Found -set-init bits that are not part of the initial_state: %s\n", log_signal(rem));
153  }
154 
155  if (set_init_def) {
157  std::vector<int> undef_rem = satgen.importUndefSigSpec(rem, 1);
158  ez.assume(ez.NOT(ez.expression(ezSAT::OpOr, undef_rem)));
159  }
160 
161  if (set_init_undef) {
163  rem.remove(big_lhs);
164  big_lhs.append(rem);
165  big_rhs.append(RTLIL::SigSpec(RTLIL::State::Sx, rem.size()));
166  }
167 
168  if (set_init_zero) {
170  rem.remove(big_lhs);
171  big_lhs.append(rem);
172  big_rhs.append(RTLIL::SigSpec(RTLIL::State::S0, rem.size()));
173  }
174 
175  if (big_lhs.size() == 0) {
176  log("No constraints for initial state found.\n\n");
177  return;
178  }
179 
180  log("Final constraint equation: %s = %s\n\n", log_signal(big_lhs), log_signal(big_rhs));
181  check_undef_enabled(big_lhs), check_undef_enabled(big_rhs);
182  ez.assume(satgen.signals_eq(big_lhs, big_rhs, 1));
183  }
184 
185  void setup(int timestep = -1)
186  {
187  if (timestep > 0)
188  log ("\nSetting up time step %d:\n", timestep);
189  else
190  log ("\nSetting up SAT problem:\n");
191 
192  if (timestep > max_timestep)
193  max_timestep = timestep;
194 
195  RTLIL::SigSpec big_lhs, big_rhs;
196 
197  for (auto &s : sets)
198  {
199  RTLIL::SigSpec lhs, rhs;
200 
201  if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s.first))
202  log_cmd_error("Failed to parse lhs set expression `%s'.\n", s.first.c_str());
203  if (!RTLIL::SigSpec::parse_rhs(lhs, rhs, module, s.second))
204  log_cmd_error("Failed to parse rhs set expression `%s'.\n", s.second.c_str());
207 
208  if (lhs.size() != rhs.size())
209  log_cmd_error("Set expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
210  s.first.c_str(), log_signal(lhs), lhs.size(), s.second.c_str(), log_signal(rhs), rhs.size());
211 
212  log("Import set-constraint: %s = %s\n", log_signal(lhs), log_signal(rhs));
213  big_lhs.remove2(lhs, &big_rhs);
214  big_lhs.append(lhs);
215  big_rhs.append(rhs);
216  }
217 
218  for (auto &s : sets_at[timestep])
219  {
220  RTLIL::SigSpec lhs, rhs;
221 
222  if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s.first))
223  log_cmd_error("Failed to parse lhs set expression `%s'.\n", s.first.c_str());
224  if (!RTLIL::SigSpec::parse_rhs(lhs, rhs, module, s.second))
225  log_cmd_error("Failed to parse rhs set expression `%s'.\n", s.second.c_str());
228 
229  if (lhs.size() != rhs.size())
230  log_cmd_error("Set expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
231  s.first.c_str(), log_signal(lhs), lhs.size(), s.second.c_str(), log_signal(rhs), rhs.size());
232 
233  log("Import set-constraint for this timestep: %s = %s\n", log_signal(lhs), log_signal(rhs));
234  big_lhs.remove2(lhs, &big_rhs);
235  big_lhs.append(lhs);
236  big_rhs.append(rhs);
237  }
238 
239  for (auto &s : unsets_at[timestep])
240  {
241  RTLIL::SigSpec lhs;
242 
243  if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s))
244  log_cmd_error("Failed to parse lhs set expression `%s'.\n", s.c_str());
246 
247  log("Import unset-constraint for this timestep: %s\n", log_signal(lhs));
248  big_lhs.remove2(lhs, &big_rhs);
249  }
250 
251  log("Final constraint equation: %s = %s\n", log_signal(big_lhs), log_signal(big_rhs));
252  check_undef_enabled(big_lhs), check_undef_enabled(big_rhs);
253  ez.assume(satgen.signals_eq(big_lhs, big_rhs, timestep));
254 
255  // 0 = sets_def
256  // 1 = sets_any_undef
257  // 2 = sets_all_undef
258  std::set<RTLIL::SigSpec> sets_def_undef[3];
259 
260  for (auto &s : sets_def) {
261  RTLIL::SigSpec sig;
262  if (!RTLIL::SigSpec::parse_sel(sig, design, module, s))
263  log_cmd_error("Failed to parse set-def expression `%s'.\n", s.c_str());
264  sets_def_undef[0].insert(sig);
265  }
266 
267  for (auto &s : sets_any_undef) {
268  RTLIL::SigSpec sig;
269  if (!RTLIL::SigSpec::parse_sel(sig, design, module, s))
270  log_cmd_error("Failed to parse set-def expression `%s'.\n", s.c_str());
271  sets_def_undef[1].insert(sig);
272  }
273 
274  for (auto &s : sets_all_undef) {
275  RTLIL::SigSpec sig;
276  if (!RTLIL::SigSpec::parse_sel(sig, design, module, s))
277  log_cmd_error("Failed to parse set-def expression `%s'.\n", s.c_str());
278  sets_def_undef[2].insert(sig);
279  }
280 
281  for (auto &s : sets_def_at[timestep]) {
282  RTLIL::SigSpec sig;
283  if (!RTLIL::SigSpec::parse_sel(sig, design, module, s))
284  log_cmd_error("Failed to parse set-def expression `%s'.\n", s.c_str());
285  sets_def_undef[0].insert(sig);
286  sets_def_undef[1].erase(sig);
287  sets_def_undef[2].erase(sig);
288  }
289 
290  for (auto &s : sets_any_undef_at[timestep]) {
291  RTLIL::SigSpec sig;
292  if (!RTLIL::SigSpec::parse_sel(sig, design, module, s))
293  log_cmd_error("Failed to parse set-def expression `%s'.\n", s.c_str());
294  sets_def_undef[0].erase(sig);
295  sets_def_undef[1].insert(sig);
296  sets_def_undef[2].erase(sig);
297  }
298 
299  for (auto &s : sets_all_undef_at[timestep]) {
300  RTLIL::SigSpec sig;
301  if (!RTLIL::SigSpec::parse_sel(sig, design, module, s))
302  log_cmd_error("Failed to parse set-def expression `%s'.\n", s.c_str());
303  sets_def_undef[0].erase(sig);
304  sets_def_undef[1].erase(sig);
305  sets_def_undef[2].insert(sig);
306  }
307 
308  for (int t = 0; t < 3; t++)
309  for (auto &sig : sets_def_undef[t]) {
310  log("Import %s constraint for this timestep: %s\n", t == 0 ? "def" : t == 1 ? "any_undef" : "all_undef", log_signal(sig));
311  std::vector<int> undef_sig = satgen.importUndefSigSpec(sig, timestep);
312  if (t == 0)
313  ez.assume(ez.NOT(ez.expression(ezSAT::OpOr, undef_sig)));
314  if (t == 1)
315  ez.assume(ez.expression(ezSAT::OpOr, undef_sig));
316  if (t == 2)
317  ez.assume(ez.expression(ezSAT::OpAnd, undef_sig));
318  }
319 
320  int import_cell_counter = 0;
321  for (auto &c : module->cells_)
322  if (design->selected(module, c.second)) {
323  // log("Import cell: %s\n", RTLIL::id2cstr(c.first));
324  if (satgen.importCell(c.second, timestep)) {
325  for (auto &p : c.second->connections())
326  if (ct.cell_output(c.second->type, p.first))
327  show_drivers.insert(sigmap(p.second), c.second);
328  import_cell_counter++;
329  } else if (ignore_unknown_cells)
330  log_warning("Failed to import cell %s (type %s) to SAT database.\n", RTLIL::id2cstr(c.first), RTLIL::id2cstr(c.second->type));
331  else
332  log_error("Failed to import cell %s (type %s) to SAT database.\n", RTLIL::id2cstr(c.first), RTLIL::id2cstr(c.second->type));
333  }
334  log("Imported %d cells to SAT database.\n", import_cell_counter);
335  }
336 
337  int setup_proof(int timestep = -1)
338  {
339  log_assert(prove.size() || prove_x.size() || prove_asserts);
340 
341  RTLIL::SigSpec big_lhs, big_rhs;
342  std::vector<int> prove_bits;
343 
344  if (prove.size() > 0)
345  {
346  for (auto &s : prove)
347  {
348  RTLIL::SigSpec lhs, rhs;
349 
350  if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s.first))
351  log_cmd_error("Failed to parse lhs proof expression `%s'.\n", s.first.c_str());
352  if (!RTLIL::SigSpec::parse_rhs(lhs, rhs, module, s.second))
353  log_cmd_error("Failed to parse rhs proof expression `%s'.\n", s.second.c_str());
356 
357  if (lhs.size() != rhs.size())
358  log_cmd_error("Proof expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
359  s.first.c_str(), log_signal(lhs), lhs.size(), s.second.c_str(), log_signal(rhs), rhs.size());
360 
361  log("Import proof-constraint: %s = %s\n", log_signal(lhs), log_signal(rhs));
362  big_lhs.remove2(lhs, &big_rhs);
363  big_lhs.append(lhs);
364  big_rhs.append(rhs);
365  }
366 
367  log("Final proof equation: %s = %s\n", log_signal(big_lhs), log_signal(big_rhs));
368  check_undef_enabled(big_lhs), check_undef_enabled(big_rhs);
369  prove_bits.push_back(satgen.signals_eq(big_lhs, big_rhs, timestep));
370  }
371 
372  if (prove_x.size() > 0)
373  {
374  for (auto &s : prove_x)
375  {
376  RTLIL::SigSpec lhs, rhs;
377 
378  if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s.first))
379  log_cmd_error("Failed to parse lhs proof-x expression `%s'.\n", s.first.c_str());
380  if (!RTLIL::SigSpec::parse_rhs(lhs, rhs, module, s.second))
381  log_cmd_error("Failed to parse rhs proof-x expression `%s'.\n", s.second.c_str());
384 
385  if (lhs.size() != rhs.size())
386  log_cmd_error("Proof-x expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
387  s.first.c_str(), log_signal(lhs), lhs.size(), s.second.c_str(), log_signal(rhs), rhs.size());
388 
389  log("Import proof-x-constraint: %s = %s\n", log_signal(lhs), log_signal(rhs));
390  big_lhs.remove2(lhs, &big_rhs);
391  big_lhs.append(lhs);
392  big_rhs.append(rhs);
393  }
394 
395  log("Final proof-x equation: %s = %s\n", log_signal(big_lhs), log_signal(big_rhs));
396 
397  std::vector<int> value_lhs = satgen.importDefSigSpec(big_lhs, timestep);
398  std::vector<int> value_rhs = satgen.importDefSigSpec(big_rhs, timestep);
399 
400  std::vector<int> undef_lhs = satgen.importUndefSigSpec(big_lhs, timestep);
401  std::vector<int> undef_rhs = satgen.importUndefSigSpec(big_rhs, timestep);
402 
403  for (size_t i = 0; i < value_lhs.size(); i++)
404  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))))));
405  }
406 
407  if (prove_asserts) {
408  RTLIL::SigSpec asserts_a, asserts_en;
409  satgen.getAsserts(asserts_a, asserts_en, timestep);
410  for (int i = 0; i < GetSize(asserts_a); i++)
411  log("Import proof for assert: %s when %s.\n", log_signal(asserts_a[i]), log_signal(asserts_en[i]));
412  prove_bits.push_back(satgen.importAsserts(timestep));
413  }
414 
415  return ez.expression(ezSAT::OpAnd, prove_bits);
416  }
417 
418  void force_unique_state(int timestep_from, int timestep_to)
419  {
420  RTLIL::SigSpec state_signals = satgen.initial_state.export_all();
421  for (int i = timestep_from; i < timestep_to; i++)
422  ez.assume(ez.NOT(satgen.signals_eq(state_signals, state_signals, i, timestep_to)));
423  }
424 
425  bool solve(const std::vector<int> &assumptions)
426  {
427  log_assert(gotTimeout == false);
428  ez.setSolverTimeout(timeout);
429  bool success = ez.solve(modelExpressions, modelValues, assumptions);
430  if (ez.getSolverTimoutStatus())
431  gotTimeout = true;
432  return success;
433  }
434 
435  bool solve(int a = 0, int b = 0, int c = 0, int d = 0, int e = 0, int f = 0)
436  {
437  log_assert(gotTimeout == false);
438  ez.setSolverTimeout(timeout);
439  bool success = ez.solve(modelExpressions, modelValues, a, b, c, d, e, f);
440  if (ez.getSolverTimoutStatus())
441  gotTimeout = true;
442  return success;
443  }
444 
445  struct ModelBlockInfo {
447  std::string description;
448  bool operator < (const ModelBlockInfo &other) const {
449  if (timestep != other.timestep)
450  return timestep < other.timestep;
451  if (description != other.description)
452  return description < other.description;
453  if (offset != other.offset)
454  return offset < other.offset;
455  if (width != other.width)
456  return width < other.width;
457  return false;
458  }
459  };
460 
461  std::vector<int> modelExpressions;
462  std::vector<bool> modelValues;
463  std::set<ModelBlockInfo> modelInfo;
464 
466  {
468  std::vector<bool> backupValues;
469 
470  while (1)
471  {
472  std::vector<int> must_undef, maybe_undef;
473 
474  for (size_t i = 0; i < modelExpressions.size()/2; i++)
475  if (modelValues.at(modelExpressions.size()/2 + i))
476  must_undef.push_back(modelExpressions.at(modelExpressions.size()/2 + i));
477  else
478  maybe_undef.push_back(modelExpressions.at(modelExpressions.size()/2 + i));
479 
480  backupValues.swap(modelValues);
481  if (!solve(ez.expression(ezSAT::OpAnd, must_undef), ez.expression(ezSAT::OpOr, maybe_undef)))
482  break;
483  }
484 
485  backupValues.swap(modelValues);
486  }
487 
489  {
490  RTLIL::SigSpec modelSig;
491  modelExpressions.clear();
492  modelInfo.clear();
493 
494  // Add "show" signals or alternatively the leaves on the input cone on all set and prove signals
495 
496  if (shows.size() == 0)
497  {
498  SigPool queued_signals, handled_signals, final_signals;
499  queued_signals = show_signal_pool;
500  while (queued_signals.size() > 0) {
501  RTLIL::SigSpec sig = queued_signals.export_one();
502  queued_signals.del(sig);
503  handled_signals.add(sig);
504  std::set<RTLIL::Cell*> drivers = show_drivers.find(sig);
505  if (drivers.size() == 0) {
506  final_signals.add(sig);
507  } else {
508  for (auto &d : drivers)
509  for (auto &p : d->connections()) {
510  if (d->type == "$dff" && p.first == "\\CLK")
511  continue;
512  if (d->type.substr(0, 6) == "$_DFF_" && p.first == "\\C")
513  continue;
514  queued_signals.add(handled_signals.remove(sigmap(p.second)));
515  }
516  }
517  }
518  modelSig = final_signals.export_all();
519 
520  // additionally add all set and prove signals directly
521  // (it improves user confidence if we write the constraints back ;-)
522  modelSig.append(show_signal_pool.export_all());
523  }
524  else
525  {
526  for (auto &s : shows) {
527  RTLIL::SigSpec sig;
528  if (!RTLIL::SigSpec::parse_sel(sig, design, module, s))
529  log_cmd_error("Failed to parse show expression `%s'.\n", s.c_str());
530  log("Import show expression: %s\n", log_signal(sig));
531  modelSig.append(sig);
532  }
533  }
534 
535  modelSig.sort_and_unify();
536  // log("Model signals: %s\n", log_signal(modelSig));
537 
538  std::vector<int> modelUndefExpressions;
539 
540  for (auto &c : modelSig.chunks())
541  if (c.wire != NULL)
542  {
543  ModelBlockInfo info;
544  RTLIL::SigSpec chunksig = c;
545  info.width = chunksig.size();
546  info.description = log_signal(chunksig);
547 
548  for (int timestep = -1; timestep <= max_timestep; timestep++)
549  {
550  if ((timestep == -1 && max_timestep > 0) || timestep == 0)
551  continue;
552 
553  info.timestep = timestep;
554  info.offset = modelExpressions.size();
555  modelInfo.insert(info);
556 
557  std::vector<int> vec = satgen.importSigSpec(chunksig, timestep);
558  modelExpressions.insert(modelExpressions.end(), vec.begin(), vec.end());
559 
560  if (enable_undef) {
561  std::vector<int> undef_vec = satgen.importUndefSigSpec(chunksig, timestep);
562  modelUndefExpressions.insert(modelUndefExpressions.end(), undef_vec.begin(), undef_vec.end());
563  }
564  }
565  }
566 
567  // Add initial state signals as collected by satgen
568  //
569  modelSig = satgen.initial_state.export_all();
570  for (auto &c : modelSig.chunks())
571  if (c.wire != NULL)
572  {
573  ModelBlockInfo info;
574  RTLIL::SigSpec chunksig = c;
575 
576  info.timestep = 0;
577  info.offset = modelExpressions.size();
578  info.width = chunksig.size();
579  info.description = log_signal(chunksig);
580  modelInfo.insert(info);
581 
582  std::vector<int> vec = satgen.importSigSpec(chunksig, 1);
583  modelExpressions.insert(modelExpressions.end(), vec.begin(), vec.end());
584 
585  if (enable_undef) {
586  std::vector<int> undef_vec = satgen.importUndefSigSpec(chunksig, 1);
587  modelUndefExpressions.insert(modelUndefExpressions.end(), undef_vec.begin(), undef_vec.end());
588  }
589  }
590 
591  modelExpressions.insert(modelExpressions.end(), modelUndefExpressions.begin(), modelUndefExpressions.end());
592  }
593 
594  void print_model()
595  {
596  int maxModelName = 10;
597  int maxModelWidth = 10;
598 
599  for (auto &info : modelInfo) {
600  maxModelName = std::max(maxModelName, int(info.description.size()));
601  maxModelWidth = std::max(maxModelWidth, info.width);
602  }
603 
604  log("\n");
605 
606  int last_timestep = -2;
607  for (auto &info : modelInfo)
608  {
609  RTLIL::Const value;
610  bool found_undef = false;
611 
612  for (int i = 0; i < info.width; i++) {
613  value.bits.push_back(modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0);
614  if (enable_undef && modelValues.at(modelExpressions.size()/2 + info.offset + i))
615  value.bits.back() = RTLIL::State::Sx, found_undef = true;
616  }
617 
618  if (info.timestep != last_timestep) {
619  const char *hline = "---------------------------------------------------------------------------------------------------"
620  "---------------------------------------------------------------------------------------------------"
621  "---------------------------------------------------------------------------------------------------";
622  if (last_timestep == -2) {
623  log(max_timestep > 0 ? " Time " : " ");
624  log("%-*s %10s %10s %*s\n", maxModelName+10, "Signal Name", "Dec", "Hex", maxModelWidth+5, "Bin");
625  }
626  log(max_timestep > 0 ? " ---- " : " ");
627  log("%*.*s %10.10s %10.10s %*.*s\n", maxModelName+10, maxModelName+10,
628  hline, hline, hline, maxModelWidth+5, maxModelWidth+5, hline);
629  last_timestep = info.timestep;
630  }
631 
632  if (max_timestep > 0) {
633  if (info.timestep > 0)
634  log(" %4d ", info.timestep);
635  else
636  log(" init ");
637  } else
638  log(" ");
639 
640  if (info.width <= 32 && !found_undef)
641  log("%-*s %10d %10x %*s\n", maxModelName+10, info.description.c_str(), value.as_int(), value.as_int(), maxModelWidth+5, value.as_string().c_str());
642  else
643  log("%-*s %10s %10s %*s\n", maxModelName+10, info.description.c_str(), "--", "--", maxModelWidth+5, value.as_string().c_str());
644  }
645 
646  if (last_timestep == -2)
647  log(" no model variables selected for display.\n");
648  }
649 
650  void dump_model_to_vcd(std::string vcd_file_name)
651  {
652  FILE *f = fopen(vcd_file_name.c_str(), "w");
653  if (!f)
654  log_cmd_error("Can't open output file `%s' for writing: %s\n", vcd_file_name.c_str(), strerror(errno));
655 
656  log("Dumping SAT model to VCD file %s\n", vcd_file_name.c_str());
657 
658  time_t timestamp;
659  struct tm* now;
660  char stime[128] = {};
661  time(&timestamp);
662  now = localtime(&timestamp);
663  strftime(stime, sizeof(stime), "%c", now);
664 
665  std::string module_fname = "unknown";
666  auto apos = module->attributes.find("\\src");
667  if(apos != module->attributes.end())
668  module_fname = module->attributes["\\src"].decode_string();
669 
670  fprintf(f, "$date\n");
671  fprintf(f, " %s\n", stime);
672  fprintf(f, "$end\n");
673  fprintf(f, "$version\n");
674  fprintf(f, " Generated by %s\n", yosys_version_str);
675  fprintf(f, "$end\n");
676  fprintf(f, "$comment\n");
677  fprintf(f, " Generated from SAT problem in module %s (declared at %s)\n",
678  module->name.c_str(), module_fname.c_str());
679  fprintf(f, "$end\n");
680 
681  // VCD has some limits on internal (non-display) identifier names, so make legal ones
682  std::map<std::string, std::string> vcdnames;
683 
684  fprintf(f, "$timescale 1ns\n"); // arbitrary time scale since actual clock period is unknown/unimportant
685  fprintf(f, "$scope module %s $end\n", module->name.c_str());
686  for (auto &info : modelInfo)
687  {
688  if (vcdnames.find(info.description) != vcdnames.end())
689  continue;
690 
691  char namebuf[16];
692  snprintf(namebuf, sizeof(namebuf), "v%d", static_cast<int>(vcdnames.size()));
693  vcdnames[info.description] = namebuf;
694 
695  // Even display identifiers can't use some special characters
696  std::string legal_desc = info.description.c_str();
697  for (auto &c : legal_desc) {
698  if(c == '$')
699  c = '_';
700  if(c == ':')
701  c = '_';
702  }
703 
704  fprintf(f, "$var wire %d %s %s $end\n", info.width, namebuf, legal_desc.c_str());
705 
706  // Need to look at first *two* cycles!
707  // We need to put a name on all variables but those without an initialization clause
708  // have no value at timestep 0
709  if(info.timestep > 1)
710  break;
711  }
712  fprintf(f, "$upscope $end\n");
713  fprintf(f, "$enddefinitions $end\n");
714  fprintf(f, "$dumpvars\n");
715 
716  static const char bitvals[] = "01xzxx";
717 
718  int last_timestep = -2;
719  for (auto &info : modelInfo)
720  {
721  RTLIL::Const value;
722 
723  for (int i = 0; i < info.width; i++) {
724  value.bits.push_back(modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0);
725  if (enable_undef && modelValues.at(modelExpressions.size()/2 + info.offset + i))
726  value.bits.back() = RTLIL::State::Sx;
727  }
728 
729  if (info.timestep != last_timestep) {
730  if(last_timestep == 0)
731  fprintf(f, "$end\n");
732  else
733  fprintf(f, "#%d\n", info.timestep);
734  last_timestep = info.timestep;
735  }
736 
737  if(info.width == 1) {
738  fprintf(f, "%c%s\n", bitvals[value.bits[0]], vcdnames[info.description].c_str());
739  } else {
740  fprintf(f, "b");
741  for(int k=info.width-1; k >= 0; k --) //need to flip bit ordering for VCD
742  fprintf(f, "%c", bitvals[value.bits[k]]);
743  fprintf(f, " %s\n", vcdnames[info.description].c_str());
744  }
745  }
746 
747  if (last_timestep == -2)
748  log(" no model variables selected for display.\n");
749 
750  fclose(f);
751  }
752 
753  void invalidate_model(bool max_undef)
754  {
755  std::vector<int> clause;
756  if (enable_undef) {
757  for (size_t i = 0; i < modelExpressions.size()/2; i++) {
758  int bit = modelExpressions.at(i), bit_undef = modelExpressions.at(modelExpressions.size()/2 + i);
759  bool val = modelValues.at(i), val_undef = modelValues.at(modelExpressions.size()/2 + i);
760  if (!max_undef || !val_undef)
761  clause.push_back(val_undef ? ez.NOT(bit_undef) : val ? ez.NOT(bit) : bit);
762  }
763  } else
764  for (size_t i = 0; i < modelExpressions.size(); i++)
765  clause.push_back(modelValues.at(i) ? ez.NOT(modelExpressions.at(i)) : modelExpressions.at(i));
766  ez.assume(ez.expression(ezSAT::OpOr, clause));
767  }
768 };
769 
771 {
772  log("\n");
773  log(" ______ ___ ___ _ _ _ _ \n");
774  log(" (_____ \\ / __) / __) (_) | | | |\n");
775  log(" _____) )___ ___ ___ _| |__ _| |__ _____ _| | _____ __| | |\n");
776  log(" | ____/ ___) _ \\ / _ (_ __) (_ __|____ | | || ___ |/ _ |_|\n");
777  log(" | | | | | |_| | |_| || | | | / ___ | | || ____( (_| |_ \n");
778  log(" |_| |_| \\___/ \\___/ |_| |_| \\_____|_|\\_)_____)\\____|_|\n");
779  log("\n");
780 }
781 
783 {
784  log("\n");
785  log(" _____ _ _ _____ ____ _ _____\n");
786  log(" /__ __\\/ \\/ \\__/|/ __// _ \\/ \\ /\\/__ __\\\n");
787  log(" / \\ | || |\\/||| \\ | / \\|| | || / \\\n");
788  log(" | | | || | ||| /_ | \\_/|| \\_/| | |\n");
789  log(" \\_/ \\_/\\_/ \\|\\____\\\\____/\\____/ \\_/\n");
790  log("\n");
791 }
792 
793 void print_qed()
794 {
795  log("\n");
796  log(" /$$$$$$ /$$$$$$$$ /$$$$$$$ \n");
797  log(" /$$__ $$ | $$_____/ | $$__ $$ \n");
798  log(" | $$ \\ $$ | $$ | $$ \\ $$ \n");
799  log(" | $$ | $$ | $$$$$ | $$ | $$ \n");
800  log(" | $$ | $$ | $$__/ | $$ | $$ \n");
801  log(" | $$/$$ $$ | $$ | $$ | $$ \n");
802  log(" | $$$$$$/ /$$| $$$$$$$$ /$$| $$$$$$$//$$\n");
803  log(" \\____ $$$|__/|________/|__/|_______/|__/\n");
804  log(" \\__/ \n");
805  log("\n");
806 }
807 
808 struct SatPass : public Pass {
809  SatPass() : Pass("sat", "solve a SAT problem in the circuit") { }
810  virtual void help()
811  {
812  // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
813  log("\n");
814  log(" sat [options] [selection]\n");
815  log("\n");
816  log("This command solves a SAT problem defined over the currently selected circuit\n");
817  log("and additional constraints passed as parameters.\n");
818  log("\n");
819  log(" -all\n");
820  log(" show all solutions to the problem (this can grow exponentially, use\n");
821  log(" -max <N> instead to get <N> solutions)\n");
822  log("\n");
823  log(" -max <N>\n");
824  log(" like -all, but limit number of solutions to <N>\n");
825  log("\n");
826  log(" -enable_undef\n");
827  log(" enable modeling of undef value (aka 'x-bits')\n");
828  log(" this option is implied by -set-def, -set-undef et. cetera\n");
829  log("\n");
830  log(" -max_undef\n");
831  log(" maximize the number of undef bits in solutions, giving a better\n");
832  log(" picture of which input bits are actually vital to the solution.\n");
833  log("\n");
834  log(" -set <signal> <value>\n");
835  log(" set the specified signal to the specified value.\n");
836  log("\n");
837  log(" -set-def <signal>\n");
838  log(" add a constraint that all bits of the given signal must be defined\n");
839  log("\n");
840  log(" -set-any-undef <signal>\n");
841  log(" add a constraint that at least one bit of the given signal is undefined\n");
842  log("\n");
843  log(" -set-all-undef <signal>\n");
844  log(" add a constraint that all bits of the given signal are undefined\n");
845  log("\n");
846  log(" -set-def-inputs\n");
847  log(" add -set-def constraints for all module inputs\n");
848  log("\n");
849  log(" -show <signal>\n");
850  log(" show the model for the specified signal. if no -show option is\n");
851  log(" passed then a set of signals to be shown is automatically selected.\n");
852  log("\n");
853  log(" -show-inputs, -show-outputs\n");
854  log(" add all module input (output) ports to the list of shown signals\n");
855  log("\n");
856  log(" -ignore_div_by_zero\n");
857  log(" ignore all solutions that involve a division by zero\n");
858  log("\n");
859  log(" -ignore_unknown_cells\n");
860  log(" ignore all cells that can not be matched to a SAT model\n");
861  log("\n");
862  log("The following options can be used to set up a sequential problem:\n");
863  log("\n");
864  log(" -seq <N>\n");
865  log(" set up a sequential problem with <N> time steps. The steps will\n");
866  log(" be numbered from 1 to N.\n");
867  log("\n");
868  log(" -set-at <N> <signal> <value>\n");
869  log(" -unset-at <N> <signal>\n");
870  log(" set or unset the specified signal to the specified value in the\n");
871  log(" given timestep. this has priority over a -set for the same signal.\n");
872  log("\n");
873  log(" -set-def-at <N> <signal>\n");
874  log(" -set-any-undef-at <N> <signal>\n");
875  log(" -set-all-undef-at <N> <signal>\n");
876  log(" add undef constraints in the given timestep.\n");
877  log("\n");
878  log(" -set-init <signal> <value>\n");
879  log(" set the initial value for the register driving the signal to the value\n");
880  log("\n");
881  log(" -set-init-undef\n");
882  log(" set all initial states (not set using -set-init) to undef\n");
883  log("\n");
884  log(" -set-init-def\n");
885  log(" do not force a value for the initial state but do not allow undef\n");
886  log("\n");
887  log(" -set-init-zero\n");
888  log(" set all initial states (not set using -set-init) to zero\n");
889  log("\n");
890  log(" -dump_vcd <vcd-file-name>\n");
891  log(" dump SAT model (counter example in proof) to VCD file\n");
892  log("\n");
893  log(" -dump_cnf <cnf-file-name>\n");
894  log(" dump CNF of SAT problem (in DIMACS format). in temporal induction\n");
895  log(" proofs this is the CNF of the first induction step.\n");
896  log("\n");
897  log("The following additional options can be used to set up a proof. If also -seq\n");
898  log("is passed, a temporal induction proof is performed.\n");
899  log("\n");
900  log(" -tempinduct\n");
901  log(" Perform a temporal induction proof. In a temporalinduction proof it is\n");
902  log(" proven that the condition holds forever after the number of time steps\n");
903  log(" specified using -seq.\n");
904  log("\n");
905  log(" -tempinduct-def\n");
906  log(" Perform a temporal induction proof. Assume an initial state with all\n");
907  log(" registers set to defined values for the induction step.\n");
908  log("\n");
909  log(" -prove <signal> <value>\n");
910  log(" Attempt to proof that <signal> is always <value>.\n");
911  log("\n");
912  log(" -prove-x <signal> <value>\n");
913  log(" Like -prove, but an undef (x) bit in the lhs matches any value on\n");
914  log(" the right hand side. Useful for equivialence checking.\n");
915  log("\n");
916  log(" -prove-asserts\n");
917  log(" Prove that all asserts in the design hold.\n");
918  log("\n");
919  log(" -prove-skip <N>\n");
920  log(" Do not enforce the prove-condition for the first <N> time steps.\n");
921  log("\n");
922  log(" -maxsteps <N>\n");
923  log(" Set a maximum length for the induction.\n");
924  log("\n");
925  log(" -initsteps <N>\n");
926  log(" Set initial length for the induction.\n");
927  log("\n");
928  log(" -timeout <N>\n");
929  log(" Maximum number of seconds a single SAT instance may take.\n");
930  log("\n");
931  log(" -verify\n");
932  log(" Return an error and stop the synthesis script if the proof fails.\n");
933  log("\n");
934  log(" -verify-no-timeout\n");
935  log(" Like -verify but do not return an error for timeouts.\n");
936  log("\n");
937  log(" -falsify\n");
938  log(" Return an error and stop the synthesis script if the proof succeeds.\n");
939  log("\n");
940  log(" -falsify-no-timeout\n");
941  log(" Like -falsify but do not return an error for timeouts.\n");
942  log("\n");
943  }
944  virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
945  {
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;
956 
957  log_header("Executing SAT pass (solving SAT problems in the circuit).\n");
958 
959  size_t argidx;
960  for (argidx = 1; argidx < args.size(); argidx++) {
961  if (args[argidx] == "-all") {
962  loopcount = -1;
963  continue;
964  }
965  if (args[argidx] == "-verify") {
966  fail_on_timeout = true;
967  verify = true;
968  continue;
969  }
970  if (args[argidx] == "-verify-no-timeout") {
971  verify = true;
972  continue;
973  }
974  if (args[argidx] == "-falsify") {
975  fail_on_timeout = true;
976  falsify = true;
977  continue;
978  }
979  if (args[argidx] == "-falsify-no-timeout") {
980  falsify = true;
981  continue;
982  }
983  if (args[argidx] == "-timeout" && argidx+1 < args.size()) {
984  timeout = atoi(args[++argidx].c_str());
985  continue;
986  }
987  if (args[argidx] == "-max" && argidx+1 < args.size()) {
988  loopcount = atoi(args[++argidx].c_str());
989  continue;
990  }
991  if (args[argidx] == "-maxsteps" && argidx+1 < args.size()) {
992  maxsteps = atoi(args[++argidx].c_str());
993  continue;
994  }
995  if (args[argidx] == "-initsteps" && argidx+1 < args.size()) {
996  initsteps = atoi(args[++argidx].c_str());
997  continue;
998  }
999  if (args[argidx] == "-ignore_div_by_zero") {
1000  ignore_div_by_zero = true;
1001  continue;
1002  }
1003  if (args[argidx] == "-enable_undef") {
1004  enable_undef = true;
1005  continue;
1006  }
1007  if (args[argidx] == "-max_undef") {
1008  enable_undef = true;
1009  max_undef = true;
1010  continue;
1011  }
1012  if (args[argidx] == "-set-def-inputs") {
1013  enable_undef = true;
1014  set_def_inputs = true;
1015  continue;
1016  }
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));
1021  continue;
1022  }
1023  if (args[argidx] == "-set-def" && argidx+1 < args.size()) {
1024  sets_def.push_back(args[++argidx]);
1025  enable_undef = true;
1026  continue;
1027  }
1028  if (args[argidx] == "-set-any-undef" && argidx+1 < args.size()) {
1029  sets_any_undef.push_back(args[++argidx]);
1030  enable_undef = true;
1031  continue;
1032  }
1033  if (args[argidx] == "-set-all-undef" && argidx+1 < args.size()) {
1034  sets_all_undef.push_back(args[++argidx]);
1035  enable_undef = true;
1036  continue;
1037  }
1038  if (args[argidx] == "-tempinduct") {
1039  tempinduct = true;
1040  continue;
1041  }
1042  if (args[argidx] == "-tempinduct-def") {
1043  tempinduct = true;
1044  tempinduct_def = true;
1045  continue;
1046  }
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));
1051  continue;
1052  }
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;
1058  continue;
1059  }
1060  if (args[argidx] == "-prove-asserts") {
1061  prove_asserts = true;
1062  continue;
1063  }
1064  if (args[argidx] == "-prove-skip" && argidx+1 < args.size()) {
1065  prove_skip = atoi(args[++argidx].c_str());
1066  continue;
1067  }
1068  if (args[argidx] == "-seq" && argidx+1 < args.size()) {
1069  seq_len = atoi(args[++argidx].c_str());
1070  continue;
1071  }
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));
1077  continue;
1078  }
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]);
1082  continue;
1083  }
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;
1088  continue;
1089  }
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;
1094  continue;
1095  }
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;
1100  continue;
1101  }
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));
1106  continue;
1107  }
1108  if (args[argidx] == "-set-init-undef") {
1109  set_init_undef = true;
1110  enable_undef = true;
1111  continue;
1112  }
1113  if (args[argidx] == "-set-init-def") {
1114  set_init_def = true;
1115  continue;
1116  }
1117  if (args[argidx] == "-set-init-zero") {
1118  set_init_zero = true;
1119  continue;
1120  }
1121  if (args[argidx] == "-show" && argidx+1 < args.size()) {
1122  shows.push_back(args[++argidx]);
1123  continue;
1124  }
1125  if (args[argidx] == "-show-inputs") {
1126  show_inputs = true;
1127  continue;
1128  }
1129  if (args[argidx] == "-show-outputs") {
1130  show_outputs = true;
1131  continue;
1132  }
1133  if (args[argidx] == "-ignore_unknown_cells") {
1134  ignore_unknown_cells = true;
1135  continue;
1136  }
1137  if (args[argidx] == "-dump_vcd" && argidx+1 < args.size()) {
1138  vcd_file_name = args[++argidx];
1139  continue;
1140  }
1141  if (args[argidx] == "-dump_cnf" && argidx+1 < args.size()) {
1142  cnf_file_name = args[++argidx];
1143  continue;
1144  }
1145  break;
1146  }
1147  extra_args(args, argidx, design);
1148 
1150  for (auto &mod_it : design->modules_)
1151  if (design->selected(mod_it.second)) {
1152  if (module)
1153  log_cmd_error("Only one module must be selected for the SAT pass! (selected: %s and %s)\n",
1154  RTLIL::id2cstr(module->name), RTLIL::id2cstr(mod_it.first));
1155  module = mod_it.second;
1156  }
1157  if (module == NULL)
1158  log_cmd_error("Can't perform SAT on an empty selection!\n");
1159 
1160  if (!prove.size() && !prove_x.size() && !prove_asserts && tempinduct)
1161  log_cmd_error("Got -tempinduct but nothing to prove!\n");
1162 
1163  if (prove_skip && tempinduct)
1164  log_cmd_error("Options -prove-skip and -tempinduct don't work with each other.\n");
1165 
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");
1168 
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");
1171 
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());
1176  }
1177 
1178  if (show_inputs) {
1179  for (auto &it : module->wires_)
1180  if (it.second->port_input)
1181  shows.push_back(it.second->name.str());
1182  }
1183 
1184  if (show_outputs) {
1185  for (auto &it : module->wires_)
1186  if (it.second->port_output)
1187  shows.push_back(it.second->name.str());
1188  }
1189 
1190  if (tempinduct)
1191  {
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");
1194 
1195  SatHelper basecase(design, module, enable_undef);
1196  SatHelper inductstep(design, module, enable_undef);
1197 
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;
1218 
1219  for (int timestep = 1; timestep <= seq_len; timestep++)
1220  basecase.setup(timestep);
1221  basecase.setup_init();
1222 
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;
1234 
1235  inductstep.setup(1);
1236  inductstep.ez.assume(inductstep.setup_proof(1));
1237 
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)));
1241  }
1242 
1243  for (int inductlen = 1; inductlen <= maxsteps || maxsteps == 0; inductlen++)
1244  {
1245  log("\n** Trying induction with length %d **\n", inductlen);
1246 
1247  // phase 1: proving base case
1248 
1249  basecase.setup(seq_len + inductlen);
1250  int property = basecase.setup_proof(seq_len + inductlen);
1251  basecase.generate_model();
1252 
1253  if (inductlen > 1)
1254  basecase.force_unique_state(seq_len + 1, seq_len + inductlen);
1255 
1256  log("\n[base case] Solving problem with %d variables and %d clauses..\n",
1257  basecase.ez.numCnfVariables(), basecase.ez.numCnfClauses());
1258 
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);
1265  goto tip_failed;
1266  }
1267 
1268  if (basecase.gotTimeout)
1269  goto timeout;
1270 
1271  log("Base case for induction length %d proven.\n", inductlen);
1272  basecase.ez.assume(property);
1273 
1274  // phase 2: proving induction step
1275 
1276  inductstep.setup(inductlen + 1);
1277  property = inductstep.setup_proof(inductlen + 1);
1278  inductstep.generate_model();
1279 
1280  if (inductlen > 1)
1281  inductstep.force_unique_state(1, inductlen + 1);
1282 
1283  if (inductlen < initsteps)
1284  {
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);
1288  }
1289  else
1290  {
1291  if (!cnf_file_name.empty())
1292  {
1293  FILE *f = fopen(cnf_file_name.c_str(), "w");
1294  if (!f)
1295  log_cmd_error("Can't open output file `%s' for writing: %s\n", cnf_file_name.c_str(), strerror(errno));
1296 
1297  log("Dumping CNF to file `%s'.\n", cnf_file_name.c_str());
1298  cnf_file_name.clear();
1299 
1300  inductstep.ez.printDIMACS(f, false);
1301  fclose(f);
1302  }
1303 
1304  log("\n[induction step] Solving problem with %d variables and %d clauses..\n",
1305  inductstep.ez.numCnfVariables(), inductstep.ez.numCnfClauses());
1306 
1307  if (!inductstep.solve(inductstep.ez.NOT(property))) {
1308  if (inductstep.gotTimeout)
1309  goto timeout;
1310  log("Induction step proven: SUCCESS!\n");
1311  print_qed();
1312  goto tip_success;
1313  }
1314 
1315  log("Induction step failed. Incrementing induction length.\n");
1316  inductstep.ez.assume(property);
1317  inductstep.print_model();
1318  }
1319  }
1320 
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);
1325 
1326  tip_failed:
1327  if (verify) {
1328  log("\n");
1329  log_error("Called with -verify and proof did fail!\n");
1330  }
1331 
1332  if (0)
1333  tip_success:
1334  if (falsify) {
1335  log("\n");
1336  log_error("Called with -falsify and proof did succeed!\n");
1337  }
1338  }
1339  else
1340  {
1341  if (maxsteps > 0)
1342  log_cmd_error("The options -maxsteps is only supported for temporal induction proofs!\n");
1343 
1344  SatHelper sathelper(design, module, enable_undef);
1345 
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;
1366 
1367  if (seq_len == 0) {
1368  sathelper.setup();
1369  if (sathelper.prove.size() || sathelper.prove_x.size() || sathelper.prove_asserts)
1370  sathelper.ez.assume(sathelper.ez.NOT(sathelper.setup_proof()));
1371  } else {
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));
1378  }
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();
1382  }
1383  sathelper.generate_model();
1384 
1385  if (!cnf_file_name.empty())
1386  {
1387  FILE *f = fopen(cnf_file_name.c_str(), "w");
1388  if (!f)
1389  log_cmd_error("Can't open output file `%s' for writing: %s\n", cnf_file_name.c_str(), strerror(errno));
1390 
1391  log("Dumping CNF to file `%s'.\n", cnf_file_name.c_str());
1392  cnf_file_name.clear();
1393 
1394  sathelper.ez.printDIMACS(f, false);
1395  fclose(f);
1396  }
1397 
1398  int rerun_counter = 0;
1399 
1400  rerun_solver:
1401  log("\nSolving problem with %d variables and %d clauses..\n",
1402  sathelper.ez.numCnfVariables(), sathelper.ez.numCnfClauses());
1403 
1404  if (sathelper.solve())
1405  {
1406  if (max_undef) {
1407  log("SAT model found. maximizing number of undefs.\n");
1408  sathelper.maximize_undefs();
1409  }
1410 
1411  if (!prove.size() && !prove_x.size() && !prove_asserts) {
1412  log("SAT solving finished - model found:\n");
1413  } else {
1414  log("SAT proof finished - model found: FAIL!\n");
1416  }
1417 
1418  sathelper.print_model();
1419 
1420  if(!vcd_file_name.empty())
1421  sathelper.dump_model_to_vcd(vcd_file_name);
1422 
1423  if (loopcount != 0) {
1424  loopcount--, rerun_counter++;
1425  sathelper.invalidate_model(max_undef);
1426  goto rerun_solver;
1427  }
1428 
1429  if (!prove.size() && !prove_x.size() && !prove_asserts) {
1430  if (falsify) {
1431  log("\n");
1432  log_error("Called with -falsify and found a model!\n");
1433  }
1434  } else {
1435  if (verify) {
1436  log("\n");
1437  log_error("Called with -verify and proof did fail!\n");
1438  }
1439  }
1440  }
1441  else
1442  {
1443  if (sathelper.gotTimeout)
1444  goto timeout;
1445  if (rerun_counter)
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");
1449  if (verify) {
1450  log("\n");
1451  log_error("Called with -verify and found no model!\n");
1452  }
1453  } else {
1454  log("SAT proof finished - no model found: SUCCESS!\n");
1455  print_qed();
1456  if (falsify) {
1457  log("\n");
1458  log_error("Called with -falsify and proof did succeed!\n");
1459  }
1460  }
1461  }
1462 
1463  if (!prove.size() && !prove_x.size() && !prove_asserts) {
1464  if (falsify && rerun_counter) {
1465  log("\n");
1466  log_error("Called with -falsify and found a model!\n");
1467  }
1468  } else {
1469  if (verify && rerun_counter) {
1470  log("\n");
1471  log_error("Called with -verify and proof did fail!\n");
1472  }
1473  }
1474  }
1475 
1476  if (0) {
1477  timeout:
1478  log("Interrupted SAT solver: TIMEOUT!\n");
1479  print_timeout();
1480  if (fail_on_timeout)
1481  log_error("Called with -verify and proof did time out!\n");
1482  }
1483  }
1484 } SatPass;
1485 
const char * yosys_version_str
const char * c_str() const
Definition: rtlil.h:178
bool selected(T1 *module) const
Definition: rtlil.h:551
int setup_proof(int timestep=-1)
Definition: sat.cc:337
bool ignore_div_by_zero
Definition: satgen.h:42
std::string description
Definition: sat.cc:447
void print_proof_failed()
Definition: sat.cc:770
CellTypes ct
Definition: sat.cc:46
size_t size()
Definition: sigtools.h:131
void log_warning(const char *format,...)
Definition: log.cc:196
RTLIL::SigSpec export_one()
Definition: sigtools.h:116
bool set_init_zero
Definition: sat.cc:56
int importAsserts(int timestep=-1)
Definition: satgen.h:120
static bool parse_sel(RTLIL::SigSpec &sig, RTLIL::Design *design, RTLIL::Module *module, std::string str)
Definition: rtlil.cc:3058
SigPool initial_state
Definition: satgen.h:39
void log_header(const char *format,...)
Definition: log.cc:188
std::vector< std::pair< std::string, std::string > > sets_init
Definition: sat.cc:50
void generate_model()
Definition: sat.cc:488
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
Definition: rtlil.h:595
bool prove_asserts
Definition: sat.cc:53
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
Definition: log.cc:269
void maximize_undefs()
Definition: sat.cc:465
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)
Definition: sat.cc:944
void print_model()
Definition: sat.cc:594
SatHelper(RTLIL::Design *design, RTLIL::Module *module, bool enable_undef)
Definition: sat.cc:67
std::vector< int > importSigSpec(RTLIL::SigSpec sig, int timestep=-1)
Definition: satgen.h:78
std::vector< std::string > sets_all_undef
Definition: sat.cc:57
void log_error(const char *format,...)
Definition: log.cc:204
RTLIL::Module * module
Definition: abc.cc:94
bool set_init_undef
Definition: sat.cc:56
Definition: sat.cc:808
Definition: sat.cc:39
void dump_model_to_vcd(std::string vcd_file_name)
Definition: sat.cc:650
int size() const
Definition: rtlil.h:1019
void remove(const RTLIL::SigSpec &pattern)
Definition: rtlil.cc:2342
void getAsserts(RTLIL::SigSpec &sig_a, RTLIL::SigSpec &sig_en, int timestep=-1)
Definition: satgen.h:113
std::vector< std::string > shows
Definition: sat.cc:61
bool ignore_unknown_cells
Definition: sat.cc:56
bool model_undef
Definition: satgen.h:43
std::map< int, std::vector< std::pair< std::string, std::string > > > sets_at
Definition: sat.cc:51
SigSet< RTLIL::Cell * > show_drivers
Definition: sat.cc:63
bool gotTimeout
Definition: sat.cc:65
std::vector< bool > modelValues
Definition: sat.cc:462
void force_unique_state(int timestep_from, int timestep_to)
Definition: sat.cc:418
std::vector< int > importUndefSigSpec(RTLIL::SigSpec sig, int timestep=-1)
Definition: satgen.h:92
std::vector< int > modelExpressions
Definition: sat.cc:461
YOSYS_NAMESPACE_BEGIN typedef ezMiniSAT ezDefaultSAT
Definition: satgen.h:32
std::vector< std::string > sets_any_undef
Definition: sat.cc:57
bool solve(const std::vector< int > &assumptions)
Definition: sat.cc:425
std::vector< int > importDefSigSpec(RTLIL::SigSpec sig, int timestep=-1)
Definition: satgen.h:85
std::string as_string() const
Definition: rtlil.cc:116
#define PRIVATE_NAMESPACE_BEGIN
Definition: yosys.h:97
SatPass SatPass
bool cell_output(RTLIL::IdString type, RTLIL::IdString port)
Definition: celltypes.h:193
void print_timeout()
Definition: sat.cc:782
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
void setup(int timestep=-1)
Definition: sat.cc:185
#define log_assert(_assert_expr_)
Definition: log.h:85
bool enable_undef
Definition: sat.cc:56
RTLIL::SigSpec export_all()
Definition: sigtools.h:123
RTLIL::IdString name
Definition: rtlil.h:599
std::map< int, std::vector< std::string > > sets_any_undef_at
Definition: sat.cc:58
SigMap sigmap
Definition: sat.cc:45
void remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other)
Definition: rtlil.cc:2353
#define PRIVATE_NAMESPACE_END
Definition: yosys.h:98
Definition: satgen.h:34
ezDefaultSAT ez
Definition: sat.cc:44
SatGen satgen
Definition: sat.cc:47
Definition: register.h:27
bool check_all(RTLIL::SigSpec sig)
Definition: sigtools.h:108
static const char * id2cstr(const RTLIL::IdString &str)
Definition: rtlil.h:267
std::vector< std::pair< std::string, std::string > > sets
Definition: sat.cc:50
RTLIL::SigSpec remove(RTLIL::SigSpec sig)
Definition: sigtools.h:86
void log_cmd_error(const char *format,...)
Definition: log.cc:211
int as_int(bool is_signed=false) const
Definition: rtlil.cc:104
SigPool show_signal_pool
Definition: sat.cc:62
int max_timestep
Definition: sat.cc:64
void add(RTLIL::SigSpec sig)
Definition: sigtools.h:41
bool set_init_def
Definition: sat.cc:56
#define USING_YOSYS_NAMESPACE
Definition: yosys.h:102
std::map< RTLIL::IdString, RTLIL::Module * > modules_
Definition: rtlil.h:507
void print_qed()
Definition: sat.cc:793
void sort_and_unify()
Definition: rtlil.cc:2291
int timeout
Definition: sat.cc:64
#define NULL
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
Definition: rtlil.h:596
virtual void help()
Definition: sat.cc:810
void log(const char *format,...)
Definition: log.cc:180
bool solve(int a=0, int b=0, int c=0, int d=0, int e=0, int f=0)
Definition: sat.cc:435
bool importCell(RTLIL::Cell *cell, int timestep=-1)
Definition: satgen.h:203
std::map< int, std::vector< std::string > > sets_def_at
Definition: sat.cc:58
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other=NULL) const
Definition: rtlil.cc:2414
std::vector< RTLIL::State > bits
Definition: rtlil.h:438
RTLIL::Module * module
Definition: sat.cc:42
void append(const RTLIL::SigSpec &signal)
Definition: rtlil.cc:2523
static bool parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str)
Definition: rtlil.cc:3078
std::vector< std::pair< std::string, std::string > > prove_x
Definition: sat.cc:50
void del(RTLIL::SigSpec sig)
Definition: sigtools.h:54
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
Definition: register.cc:128
bool operator<(const ModelBlockInfo &other) const
Definition: sat.cc:448
void setup_init()
Definition: sat.cc:92
RTLIL::Design * design
Definition: sat.cc:41
std::set< ModelBlockInfo > modelInfo
Definition: sat.cc:463
std::map< int, std::vector< std::string > > unsets_at
Definition: sat.cc:52
std::vector< std::pair< std::string, std::string > > prove
Definition: sat.cc:50
void find(RTLIL::SigSpec sig, std::set< T > &result)
Definition: sigtools.h:187
void insert(RTLIL::SigSpec sig, T data)
Definition: sigtools.h:152
std::vector< RTLIL::SigBit > to_sigbit_vector() const
Definition: rtlil.cc:2921
std::vector< std::string > sets_def
Definition: sat.cc:57
int signals_eq(RTLIL::SigSpec lhs, RTLIL::SigSpec rhs, int timestep_lhs=-1, int timestep_rhs=-1)
Definition: satgen.h:134
SatPass()
Definition: sat.cc:809
const std::vector< RTLIL::SigChunk > & chunks() const
Definition: rtlil.h:1016
std::map< int, std::vector< std::string > > sets_all_undef_at
Definition: sat.cc:58
void check_undef_enabled(const RTLIL::SigSpec &sig)
Definition: sat.cc:81
void invalidate_model(bool max_undef)
Definition: sat.cc:753