2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
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
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"
38 RTLIL::Design
*design
;
39 RTLIL::Module
*module
;
46 // additional constraints
47 std::vector
<std::pair
<std::string
, std::string
>> sets
, prove
, prove_x
, sets_init
;
48 std::map
<int, std::vector
<std::pair
<std::string
, std::string
>>> sets_at
;
49 std::map
<int, std::vector
<std::string
>> unsets_at
;
53 bool enable_undef
, set_init_undef
;
54 std::vector
<std::string
> sets_def
, sets_any_undef
, sets_all_undef
;
55 std::map
<int, std::vector
<std::string
>> sets_def_at
, sets_any_undef_at
, sets_all_undef_at
;
58 std::vector
<std::string
> shows
;
59 SigPool show_signal_pool
;
60 SigSet
<RTLIL::Cell
*> show_drivers
;
61 int max_timestep
, timeout
;
64 SatHelper(RTLIL::Design
*design
, RTLIL::Module
*module
, bool enable_undef
) :
65 design(design
), module(module
), sigmap(module
), ct(design
), satgen(&ez
, &sigmap
)
67 this->enable_undef
= enable_undef
;
68 satgen
.model_undef
= enable_undef
;
69 set_init_undef
= false;
75 void check_undef_enabled(const RTLIL::SigSpec
&sig
)
80 std::vector
<RTLIL::SigBit
> sigbits
= sig
.to_sigbit_vector();
81 for (size_t i
= 0; i
< sigbits
.size(); i
++)
82 if (sigbits
[i
].wire
== NULL
&& sigbits
[i
].data
== RTLIL::State::Sx
)
83 log_cmd_error("Bit %d of %s is undef but option -enable_undef is missing!\n", int(i
), log_signal(sig
));
88 log ("\nSetting up initial state:\n");
90 RTLIL::SigSpec big_lhs
, big_rhs
;
92 for (auto &s
: sets_init
)
94 RTLIL::SigSpec lhs
, rhs
;
96 if (!RTLIL::SigSpec::parse(lhs
, module
, s
.first
))
97 log_cmd_error("Failed to parse lhs set expression `%s'.\n", s
.first
.c_str());
98 if (!RTLIL::SigSpec::parse_rhs(lhs
, rhs
, module
, s
.second
))
99 log_cmd_error("Failed to parse rhs set expression `%s'.\n", s
.second
.c_str());
100 show_signal_pool
.add(sigmap(lhs
));
101 show_signal_pool
.add(sigmap(rhs
));
103 if (lhs
.width
!= rhs
.width
)
104 log_cmd_error("Set expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
105 s
.first
.c_str(), log_signal(lhs
), lhs
.width
, s
.second
.c_str(), log_signal(rhs
), rhs
.width
);
107 log("Import set-constraint: %s = %s\n", log_signal(lhs
), log_signal(rhs
));
108 big_lhs
.remove2(lhs
, &big_rhs
);
113 if (!satgen
.initial_state
.check_all(big_lhs
)) {
114 RTLIL::SigSpec rem
= satgen
.initial_state
.remove(big_lhs
);
116 log_cmd_error("Found -set-init bits that are not part of the initial_state: %s\n", log_signal(rem
));
119 if (set_init_undef
) {
120 RTLIL::SigSpec rem
= satgen
.initial_state
.export_all();
123 big_rhs
.append(RTLIL::SigSpec(RTLIL::State::Sx
, rem
.width
));
126 if (big_lhs
.width
== 0) {
127 log("No constraints for initial state found.\n\n");
131 log("Final constraint equation: %s = %s\n\n", log_signal(big_lhs
), log_signal(big_rhs
));
132 check_undef_enabled(big_lhs
), check_undef_enabled(big_rhs
);
133 ez
.assume(satgen
.signals_eq(big_lhs
, big_rhs
, 1));
136 void setup(int timestep
= -1)
139 log ("\nSetting up time step %d:\n", timestep
);
141 log ("\nSetting up SAT problem:\n");
143 if (timestep
> max_timestep
)
144 max_timestep
= timestep
;
146 RTLIL::SigSpec big_lhs
, big_rhs
;
150 RTLIL::SigSpec lhs
, rhs
;
152 if (!RTLIL::SigSpec::parse(lhs
, module
, s
.first
))
153 log_cmd_error("Failed to parse lhs set expression `%s'.\n", s
.first
.c_str());
154 if (!RTLIL::SigSpec::parse_rhs(lhs
, rhs
, module
, s
.second
))
155 log_cmd_error("Failed to parse rhs set expression `%s'.\n", s
.second
.c_str());
156 show_signal_pool
.add(sigmap(lhs
));
157 show_signal_pool
.add(sigmap(rhs
));
159 if (lhs
.width
!= rhs
.width
)
160 log_cmd_error("Set expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
161 s
.first
.c_str(), log_signal(lhs
), lhs
.width
, s
.second
.c_str(), log_signal(rhs
), rhs
.width
);
163 log("Import set-constraint: %s = %s\n", log_signal(lhs
), log_signal(rhs
));
164 big_lhs
.remove2(lhs
, &big_rhs
);
169 for (auto &s
: sets_at
[timestep
])
171 RTLIL::SigSpec lhs
, rhs
;
173 if (!RTLIL::SigSpec::parse(lhs
, module
, s
.first
))
174 log_cmd_error("Failed to parse lhs set expression `%s'.\n", s
.first
.c_str());
175 if (!RTLIL::SigSpec::parse_rhs(lhs
, rhs
, module
, s
.second
))
176 log_cmd_error("Failed to parse rhs set expression `%s'.\n", s
.second
.c_str());
177 show_signal_pool
.add(sigmap(lhs
));
178 show_signal_pool
.add(sigmap(rhs
));
180 if (lhs
.width
!= rhs
.width
)
181 log_cmd_error("Set expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
182 s
.first
.c_str(), log_signal(lhs
), lhs
.width
, s
.second
.c_str(), log_signal(rhs
), rhs
.width
);
184 log("Import set-constraint for timestep: %s = %s\n", log_signal(lhs
), log_signal(rhs
));
185 big_lhs
.remove2(lhs
, &big_rhs
);
190 for (auto &s
: unsets_at
[timestep
])
194 if (!RTLIL::SigSpec::parse(lhs
, module
, s
))
195 log_cmd_error("Failed to parse lhs set expression `%s'.\n", s
.c_str());
196 show_signal_pool
.add(sigmap(lhs
));
198 log("Import unset-constraint for timestep: %s\n", log_signal(lhs
));
199 big_lhs
.remove2(lhs
, &big_rhs
);
202 log("Final constraint equation: %s = %s\n", log_signal(big_lhs
), log_signal(big_rhs
));
203 check_undef_enabled(big_lhs
), check_undef_enabled(big_rhs
);
204 ez
.assume(satgen
.signals_eq(big_lhs
, big_rhs
, timestep
));
207 // 1 = sets_any_undef
208 // 2 = sets_all_undef
209 std::set
<RTLIL::SigSpec
> sets_def_undef
[3];
211 for (auto &s
: sets_def
) {
213 if (!RTLIL::SigSpec::parse(sig
, module
, s
))
214 log_cmd_error("Failed to parse set-def expression `%s'.\n", s
.c_str());
215 sets_def_undef
[0].insert(sig
);
218 for (auto &s
: sets_any_undef
) {
220 if (!RTLIL::SigSpec::parse(sig
, module
, s
))
221 log_cmd_error("Failed to parse set-def expression `%s'.\n", s
.c_str());
222 sets_def_undef
[1].insert(sig
);
225 for (auto &s
: sets_all_undef
) {
227 if (!RTLIL::SigSpec::parse(sig
, module
, s
))
228 log_cmd_error("Failed to parse set-def expression `%s'.\n", s
.c_str());
229 sets_def_undef
[2].insert(sig
);
232 for (auto &s
: sets_def_at
[timestep
]) {
234 if (!RTLIL::SigSpec::parse(sig
, module
, s
))
235 log_cmd_error("Failed to parse set-def expression `%s'.\n", s
.c_str());
236 sets_def_undef
[0].insert(sig
);
237 sets_def_undef
[1].erase(sig
);
238 sets_def_undef
[2].erase(sig
);
241 for (auto &s
: sets_any_undef_at
[timestep
]) {
243 if (!RTLIL::SigSpec::parse(sig
, module
, s
))
244 log_cmd_error("Failed to parse set-def expression `%s'.\n", s
.c_str());
245 sets_def_undef
[0].erase(sig
);
246 sets_def_undef
[1].insert(sig
);
247 sets_def_undef
[2].erase(sig
);
250 for (auto &s
: sets_all_undef_at
[timestep
]) {
252 if (!RTLIL::SigSpec::parse(sig
, module
, s
))
253 log_cmd_error("Failed to parse set-def expression `%s'.\n", s
.c_str());
254 sets_def_undef
[0].erase(sig
);
255 sets_def_undef
[1].erase(sig
);
256 sets_def_undef
[2].insert(sig
);
259 for (int t
= 0; t
< 3; t
++)
260 for (auto &sig
: sets_def_undef
[t
]) {
261 log("Import %s constraint for timestep: %s\n", t
== 0 ? "def" : t
== 1 ? "any_undef" : "all_undef", log_signal(sig
));
262 std::vector
<int> undef_sig
= satgen
.importUndefSigSpec(sig
, timestep
);
264 ez
.assume(ez
.NOT(ez
.expression(ezSAT::OpOr
, undef_sig
)));
266 ez
.assume(ez
.expression(ezSAT::OpOr
, undef_sig
));
268 ez
.assume(ez
.expression(ezSAT::OpAnd
, undef_sig
));
271 int import_cell_counter
= 0;
272 for (auto &c
: module
->cells
)
273 if (design
->selected(module
, c
.second
)) {
274 // log("Import cell: %s\n", RTLIL::id2cstr(c.first));
275 if (satgen
.importCell(c
.second
, timestep
)) {
276 for (auto &p
: c
.second
->connections
)
277 if (ct
.cell_output(c
.second
->type
, p
.first
))
278 show_drivers
.insert(sigmap(p
.second
), c
.second
);
279 import_cell_counter
++;
281 log("Warning: failed to import cell %s (type %s) to SAT database.\n", RTLIL::id2cstr(c
.first
), RTLIL::id2cstr(c
.second
->type
));
283 log("Imported %d cells to SAT database.\n", import_cell_counter
);
286 int setup_proof(int timestep
= -1)
288 assert(prove
.size() || prove_x
.size() || prove_asserts
);
290 RTLIL::SigSpec big_lhs
, big_rhs
;
291 std::vector
<int> prove_bits
;
293 if (prove
.size() > 0)
295 for (auto &s
: prove
)
297 RTLIL::SigSpec lhs
, rhs
;
299 if (!RTLIL::SigSpec::parse(lhs
, module
, s
.first
))
300 log_cmd_error("Failed to parse lhs proof expression `%s'.\n", s
.first
.c_str());
301 if (!RTLIL::SigSpec::parse_rhs(lhs
, rhs
, module
, s
.second
))
302 log_cmd_error("Failed to parse rhs proof expression `%s'.\n", s
.second
.c_str());
303 show_signal_pool
.add(sigmap(lhs
));
304 show_signal_pool
.add(sigmap(rhs
));
306 if (lhs
.width
!= rhs
.width
)
307 log_cmd_error("Proof expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
308 s
.first
.c_str(), log_signal(lhs
), lhs
.width
, s
.second
.c_str(), log_signal(rhs
), rhs
.width
);
310 log("Import proof-constraint: %s = %s\n", log_signal(lhs
), log_signal(rhs
));
311 big_lhs
.remove2(lhs
, &big_rhs
);
316 log("Final proof equation: %s = %s\n", log_signal(big_lhs
), log_signal(big_rhs
));
317 check_undef_enabled(big_lhs
), check_undef_enabled(big_rhs
);
318 prove_bits
.push_back(satgen
.signals_eq(big_lhs
, big_rhs
, timestep
));
321 if (prove_x
.size() > 0)
323 for (auto &s
: prove_x
)
325 RTLIL::SigSpec lhs
, rhs
;
327 if (!RTLIL::SigSpec::parse(lhs
, module
, s
.first
))
328 log_cmd_error("Failed to parse lhs proof-x expression `%s'.\n", s
.first
.c_str());
329 if (!RTLIL::SigSpec::parse_rhs(lhs
, rhs
, module
, s
.second
))
330 log_cmd_error("Failed to parse rhs proof-x expression `%s'.\n", s
.second
.c_str());
331 show_signal_pool
.add(sigmap(lhs
));
332 show_signal_pool
.add(sigmap(rhs
));
334 if (lhs
.width
!= rhs
.width
)
335 log_cmd_error("Proof-x expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
336 s
.first
.c_str(), log_signal(lhs
), lhs
.width
, s
.second
.c_str(), log_signal(rhs
), rhs
.width
);
338 log("Import proof-x-constraint: %s = %s\n", log_signal(lhs
), log_signal(rhs
));
339 big_lhs
.remove2(lhs
, &big_rhs
);
344 log("Final proof-x equation: %s = %s\n", log_signal(big_lhs
), log_signal(big_rhs
));
346 std::vector
<int> value_lhs
= satgen
.importDefSigSpec(big_lhs
, timestep
);
347 std::vector
<int> value_rhs
= satgen
.importDefSigSpec(big_rhs
, timestep
);
349 std::vector
<int> undef_lhs
= satgen
.importUndefSigSpec(big_lhs
, timestep
);
350 std::vector
<int> undef_rhs
= satgen
.importUndefSigSpec(big_rhs
, timestep
);
352 for (size_t i
= 0; i
< value_lhs
.size(); i
++)
353 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
))))));
357 prove_bits
.push_back(satgen
.importAsserts(timestep
));
359 return ez
.expression(ezSAT::OpAnd
, prove_bits
);
362 void force_unique_state(int timestep_from
, int timestep_to
)
364 RTLIL::SigSpec state_signals
= satgen
.initial_state
.export_all();
365 for (int i
= timestep_from
; i
< timestep_to
; i
++)
366 ez
.assume(ez
.NOT(satgen
.signals_eq(state_signals
, state_signals
, i
, timestep_to
)));
369 bool solve(const std::vector
<int> &assumptions
)
371 log_assert(gotTimeout
== false);
372 ez
.setSolverTimeout(timeout
);
373 bool success
= ez
.solve(modelExpressions
, modelValues
, assumptions
);
374 if (ez
.getSolverTimoutStatus())
379 bool solve(int a
= 0, int b
= 0, int c
= 0, int d
= 0, int e
= 0, int f
= 0)
381 log_assert(gotTimeout
== false);
382 ez
.setSolverTimeout(timeout
);
383 bool success
= ez
.solve(modelExpressions
, modelValues
, a
, b
, c
, d
, e
, f
);
384 if (ez
.getSolverTimoutStatus())
389 struct ModelBlockInfo
{
390 int timestep
, offset
, width
;
391 std::string description
;
392 bool operator < (const ModelBlockInfo
&other
) const {
393 if (timestep
!= other
.timestep
)
394 return timestep
< other
.timestep
;
395 if (description
!= other
.description
)
396 return description
< other
.description
;
397 if (offset
!= other
.offset
)
398 return offset
< other
.offset
;
399 if (width
!= other
.width
)
400 return width
< other
.width
;
405 std::vector
<int> modelExpressions
;
406 std::vector
<bool> modelValues
;
407 std::set
<ModelBlockInfo
> modelInfo
;
409 void maximize_undefs()
411 log_assert(enable_undef
);
412 std::vector
<bool> backupValues
;
416 std::vector
<int> must_undef
, maybe_undef
;
418 for (size_t i
= 0; i
< modelExpressions
.size()/2; i
++)
419 if (modelValues
.at(modelExpressions
.size()/2 + i
))
420 must_undef
.push_back(modelExpressions
.at(modelExpressions
.size()/2 + i
));
422 maybe_undef
.push_back(modelExpressions
.at(modelExpressions
.size()/2 + i
));
424 backupValues
.swap(modelValues
);
425 if (!solve(ez
.expression(ezSAT::OpAnd
, must_undef
), ez
.expression(ezSAT::OpOr
, maybe_undef
)))
429 backupValues
.swap(modelValues
);
432 void generate_model()
434 RTLIL::SigSpec modelSig
;
435 modelExpressions
.clear();
438 // Add "show" signals or alternatively the leaves on the input cone on all set and prove signals
440 if (shows
.size() == 0)
442 SigPool queued_signals
, handled_signals
, final_signals
;
443 queued_signals
= show_signal_pool
;
444 while (queued_signals
.size() > 0) {
445 RTLIL::SigSpec sig
= queued_signals
.export_one();
446 queued_signals
.del(sig
);
447 handled_signals
.add(sig
);
448 std::set
<RTLIL::Cell
*> drivers
= show_drivers
.find(sig
);
449 if (drivers
.size() == 0) {
450 final_signals
.add(sig
);
452 for (auto &d
: drivers
)
453 for (auto &p
: d
->connections
) {
454 if (d
->type
== "$dff" && p
.first
== "\\CLK")
456 if (d
->type
.substr(0, 6) == "$_DFF_" && p
.first
== "\\C")
458 queued_signals
.add(handled_signals
.remove(sigmap(p
.second
)));
462 modelSig
= final_signals
.export_all();
464 // additionally add all set and prove signals directly
465 // (it improves user confidence if we write the constraints back ;-)
466 modelSig
.append(show_signal_pool
.export_all());
470 for (auto &s
: shows
) {
472 if (!RTLIL::SigSpec::parse(sig
, module
, s
))
473 log_cmd_error("Failed to parse show expression `%s'.\n", s
.c_str());
474 log("Import show expression: %s\n", log_signal(sig
));
475 modelSig
.append(sig
);
479 modelSig
.sort_and_unify();
480 // log("Model signals: %s\n", log_signal(modelSig));
482 std::vector
<int> modelUndefExpressions
;
484 for (auto &c
: modelSig
.chunks
)
488 RTLIL::SigSpec chunksig
= c
;
489 info
.width
= chunksig
.width
;
490 info
.description
= log_signal(chunksig
);
492 for (int timestep
= -1; timestep
<= max_timestep
; timestep
++)
494 if ((timestep
== -1 && max_timestep
> 0) || timestep
== 0)
497 info
.timestep
= timestep
;
498 info
.offset
= modelExpressions
.size();
499 modelInfo
.insert(info
);
501 std::vector
<int> vec
= satgen
.importSigSpec(chunksig
, timestep
);
502 modelExpressions
.insert(modelExpressions
.end(), vec
.begin(), vec
.end());
505 std::vector
<int> undef_vec
= satgen
.importUndefSigSpec(chunksig
, timestep
);
506 modelUndefExpressions
.insert(modelUndefExpressions
.end(), undef_vec
.begin(), undef_vec
.end());
511 // Add initial state signals as collected by satgen
513 modelSig
= satgen
.initial_state
.export_all();
514 for (auto &c
: modelSig
.chunks
)
518 RTLIL::SigSpec chunksig
= c
;
521 info
.offset
= modelExpressions
.size();
522 info
.width
= chunksig
.width
;
523 info
.description
= log_signal(chunksig
);
524 modelInfo
.insert(info
);
526 std::vector
<int> vec
= satgen
.importSigSpec(chunksig
, 1);
527 modelExpressions
.insert(modelExpressions
.end(), vec
.begin(), vec
.end());
530 std::vector
<int> undef_vec
= satgen
.importUndefSigSpec(chunksig
, 1);
531 modelUndefExpressions
.insert(modelUndefExpressions
.end(), undef_vec
.begin(), undef_vec
.end());
535 modelExpressions
.insert(modelExpressions
.end(), modelUndefExpressions
.begin(), modelUndefExpressions
.end());
540 int maxModelName
= 10;
541 int maxModelWidth
= 10;
543 for (auto &info
: modelInfo
) {
544 maxModelName
= std::max(maxModelName
, int(info
.description
.size()));
545 maxModelWidth
= std::max(maxModelWidth
, info
.width
);
550 int last_timestep
= -2;
551 for (auto &info
: modelInfo
)
554 bool found_undef
= false;
556 for (int i
= 0; i
< info
.width
; i
++) {
557 value
.bits
.push_back(modelValues
.at(info
.offset
+i
) ? RTLIL::State::S1
: RTLIL::State::S0
);
558 if (enable_undef
&& modelValues
.at(modelExpressions
.size()/2 + info
.offset
+ i
))
559 value
.bits
.back() = RTLIL::State::Sx
, found_undef
= true;
562 if (info
.timestep
!= last_timestep
) {
563 const char *hline
= "---------------------------------------------------------------------------------------------------"
564 "---------------------------------------------------------------------------------------------------"
565 "---------------------------------------------------------------------------------------------------";
566 if (last_timestep
== -2) {
567 log(max_timestep
> 0 ? " Time " : " ");
568 log("%-*s %10s %10s %*s\n", maxModelName
+10, "Signal Name", "Dec", "Hex", maxModelWidth
+5, "Bin");
570 log(max_timestep
> 0 ? " ---- " : " ");
571 log("%*.*s %10.10s %10.10s %*.*s\n", maxModelName
+10, maxModelName
+10,
572 hline
, hline
, hline
, maxModelWidth
+5, maxModelWidth
+5, hline
);
573 last_timestep
= info
.timestep
;
576 if (max_timestep
> 0) {
577 if (info
.timestep
> 0)
578 log(" %4d ", info
.timestep
);
584 if (info
.width
<= 32 && !found_undef
)
585 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());
587 log("%-*s %10s %10s %*s\n", maxModelName
+10, info
.description
.c_str(), "--", "--", maxModelWidth
+5, value
.as_string().c_str());
590 if (last_timestep
== -2)
591 log(" no model variables selected for display.\n");
594 void invalidate_model(bool max_undef
)
596 std::vector
<int> clause
;
598 for (size_t i
= 0; i
< modelExpressions
.size()/2; i
++) {
599 int bit
= modelExpressions
.at(i
), bit_undef
= modelExpressions
.at(modelExpressions
.size()/2 + i
);
600 bool val
= modelValues
.at(i
), val_undef
= modelValues
.at(modelExpressions
.size()/2 + i
);
601 if (!max_undef
|| !val_undef
)
602 clause
.push_back(val_undef
? ez
.NOT(bit_undef
) : val
? ez
.NOT(bit
) : bit
);
605 for (size_t i
= 0; i
< modelExpressions
.size(); i
++)
606 clause
.push_back(modelValues
.at(i
) ? ez
.NOT(modelExpressions
.at(i
)) : modelExpressions
.at(i
));
607 ez
.assume(ez
.expression(ezSAT::OpOr
, clause
));
613 static void print_proof_failed()
616 log(" ______ ___ ___ _ _ _ _ \n");
617 log(" (_____ \\ / __) / __) (_) | | | |\n");
618 log(" _____) )___ ___ ___ _| |__ _| |__ _____ _| | _____ __| | |\n");
619 log(" | ____/ ___) _ \\ / _ (_ __) (_ __|____ | | || ___ |/ _ |_|\n");
620 log(" | | | | | |_| | |_| || | | | / ___ | | || ____( (_| |_ \n");
621 log(" |_| |_| \\___/ \\___/ |_| |_| \\_____|_|\\_)_____)\\____|_|\n");
625 static void print_timeout()
628 log(" _____ _ _ _____ ____ _ _____\n");
629 log(" /__ __\\/ \\/ \\__/|/ __// _ \\/ \\ /\\/__ __\\\n");
630 log(" / \\ | || |\\/||| \\ | / \\|| | || / \\\n");
631 log(" | | | || | ||| /_ | \\_/|| \\_/| | |\n");
632 log(" \\_/ \\_/\\_/ \\|\\____\\\\____/\\____/ \\_/\n");
636 static void print_qed()
639 log(" /$$$$$$ /$$$$$$$$ /$$$$$$$ \n");
640 log(" /$$__ $$ | $$_____/ | $$__ $$ \n");
641 log(" | $$ \\ $$ | $$ | $$ \\ $$ \n");
642 log(" | $$ | $$ | $$$$$ | $$ | $$ \n");
643 log(" | $$ | $$ | $$__/ | $$ | $$ \n");
644 log(" | $$/$$ $$ | $$ | $$ | $$ \n");
645 log(" | $$$$$$/ /$$| $$$$$$$$ /$$| $$$$$$$//$$\n");
646 log(" \\____ $$$|__/|________/|__/|_______/|__/\n");
651 struct SatPass
: public Pass
{
652 SatPass() : Pass("sat", "solve a SAT problem in the circuit") { }
655 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
657 log(" sat [options] [selection]\n");
659 log("This command solves a SAT problem defined over the currently selected circuit\n");
660 log("and additional constraints passed as parameters.\n");
663 log(" show all solutions to the problem (this can grow exponentially, use\n");
664 log(" -max <N> instead to get <N> solutions)\n");
667 log(" like -all, but limit number of solutions to <N>\n");
669 log(" -enable_undef\n");
670 log(" enable modeling of undef value (aka 'x-bits')\n");
671 log(" this option is implied by -set-def, -set-undef et. cetera\n");
673 log(" -max_undef\n");
674 log(" maximize the number of undef bits in solutions, giving a better\n");
675 log(" picture of which input bits are actually vital to the solution.\n");
677 log(" -set <signal> <value>\n");
678 log(" set the specified signal to the specified value.\n");
680 log(" -set-def <signal>\n");
681 log(" add a constraint that all bits of the given signal must be defined\n");
683 log(" -set-any-undef <signal>\n");
684 log(" add a constraint that at least one bit of the given signal is undefined\n");
686 log(" -set-all-undef <signal>\n");
687 log(" add a constraint that all bits of the given signal are undefined\n");
689 log(" -set-def-inputs\n");
690 log(" add -set-def constraints for all module inputs\n");
692 log(" -show <signal>\n");
693 log(" show the model for the specified signal. if no -show option is\n");
694 log(" passed then a set of signals to be shown is automatically selected.\n");
696 log(" -show-inputs, -show-outputs\n");
697 log(" add all module input (output) ports to the list of shown signals\n");
699 log(" -ignore_div_by_zero\n");
700 log(" ignore all solutions that involve a division by zero\n");
702 log("The following options can be used to set up a sequential problem:\n");
705 log(" set up a sequential problem with <N> time steps. The steps will\n");
706 log(" be numbered from 1 to N.\n");
708 log(" -set-at <N> <signal> <value>\n");
709 log(" -unset-at <N> <signal>\n");
710 log(" set or unset the specified signal to the specified value in the\n");
711 log(" given timestep. this has priority over a -set for the same signal.\n");
713 log(" -set-def-at <N> <signal>\n");
714 log(" -set-any-undef-at <N> <signal>\n");
715 log(" -set-all-undef-at <N> <signal>\n");
716 log(" add undef contraints in the given timestep.\n");
718 log(" -set-init <signal> <value>\n");
719 log(" set the initial value for the register driving the signal to the value\n");
721 log(" -set-init-undef\n");
722 log(" set all initial states (not set using -set-init) to undef\n");
724 log("The following additional options can be used to set up a proof. If also -seq\n");
725 log("is passed, a temporal induction proof is performed.\n");
727 log(" -tempinduct\n");
728 log(" Perform a temporal induction proof. In a temporalinduction proof it is\n");
729 log(" proven that the condition holds forever after the number of time steps\n");
730 log(" specified using -seq.\n");
732 log(" -prove <signal> <value>\n");
733 log(" Attempt to proof that <signal> is always <value>.\n");
735 log(" -prove-x <signal> <value>\n");
736 log(" Like -prove, but an undef (x) bit in the lhs matches any value on\n");
737 log(" the right hand side. Useful for equivialence checking.\n");
739 log(" -prove-asserts\n");
740 log(" Prove that all asserts in the design hold.\n");
742 log(" -maxsteps <N>\n");
743 log(" Set a maximum length for the induction.\n");
745 log(" -timeout <N>\n");
746 log(" Maximum number of seconds a single SAT instance may take.\n");
749 log(" Return an error and stop the synthesis script if the proof fails.\n");
751 log(" -verify-no-timeout\n");
752 log(" Like -verify but do not return an error for timeouts.\n");
755 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
757 std::vector
<std::pair
<std::string
, std::string
>> sets
, sets_init
, prove
, prove_x
;
758 std::map
<int, std::vector
<std::pair
<std::string
, std::string
>>> sets_at
;
759 std::map
<int, std::vector
<std::string
>> unsets_at
, sets_def_at
, sets_any_undef_at
, sets_all_undef_at
;
760 std::vector
<std::string
> shows
, sets_def
, sets_any_undef
, sets_all_undef
;
761 int loopcount
= 0, seq_len
= 0, maxsteps
= 0, timeout
= 0;
762 bool verify
= false, fail_on_timeout
= false, enable_undef
= false, set_def_inputs
= false;
763 bool ignore_div_by_zero
= false, set_init_undef
= false, max_undef
= false;
764 bool tempinduct
= false, prove_asserts
= false, show_inputs
= false, show_outputs
= false;
766 log_header("Executing SAT pass (solving SAT problems in the circuit).\n");
769 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
770 if (args
[argidx
] == "-all") {
774 if (args
[argidx
] == "-verify") {
775 fail_on_timeout
= true;
779 if (args
[argidx
] == "-verify-no-timeout") {
783 if (args
[argidx
] == "-timeout" && argidx
+1 < args
.size()) {
784 timeout
= atoi(args
[++argidx
].c_str());
787 if (args
[argidx
] == "-max" && argidx
+1 < args
.size()) {
788 loopcount
= atoi(args
[++argidx
].c_str());
791 if (args
[argidx
] == "-maxsteps" && argidx
+1 < args
.size()) {
792 maxsteps
= atoi(args
[++argidx
].c_str());
795 if (args
[argidx
] == "-ignore_div_by_zero") {
796 ignore_div_by_zero
= true;
799 if (args
[argidx
] == "-enable_undef") {
803 if (args
[argidx
] == "-max_undef") {
808 if (args
[argidx
] == "-set-def-inputs") {
810 set_def_inputs
= true;
813 if (args
[argidx
] == "-set" && argidx
+2 < args
.size()) {
814 std::string lhs
= args
[++argidx
];
815 std::string rhs
= args
[++argidx
];
816 sets
.push_back(std::pair
<std::string
, std::string
>(lhs
, rhs
));
819 if (args
[argidx
] == "-set-def" && argidx
+1 < args
.size()) {
820 sets_def
.push_back(args
[++argidx
]);
824 if (args
[argidx
] == "-set-any-undef" && argidx
+1 < args
.size()) {
825 sets_any_undef
.push_back(args
[++argidx
]);
829 if (args
[argidx
] == "-set-all-undef" && argidx
+1 < args
.size()) {
830 sets_all_undef
.push_back(args
[++argidx
]);
834 if (args
[argidx
] == "-tempinduct") {
838 if (args
[argidx
] == "-prove" && argidx
+2 < args
.size()) {
839 std::string lhs
= args
[++argidx
];
840 std::string rhs
= args
[++argidx
];
841 prove
.push_back(std::pair
<std::string
, std::string
>(lhs
, rhs
));
844 if (args
[argidx
] == "-prove-x" && argidx
+2 < args
.size()) {
845 std::string lhs
= args
[++argidx
];
846 std::string rhs
= args
[++argidx
];
847 prove_x
.push_back(std::pair
<std::string
, std::string
>(lhs
, rhs
));
851 if (args
[argidx
] == "-prove-asserts") {
852 prove_asserts
= true;
855 if (args
[argidx
] == "-seq" && argidx
+1 < args
.size()) {
856 seq_len
= atoi(args
[++argidx
].c_str());
859 if (args
[argidx
] == "-set-at" && argidx
+3 < args
.size()) {
860 int timestep
= atoi(args
[++argidx
].c_str());
861 std::string lhs
= args
[++argidx
];
862 std::string rhs
= args
[++argidx
];
863 sets_at
[timestep
].push_back(std::pair
<std::string
, std::string
>(lhs
, rhs
));
866 if (args
[argidx
] == "-unset-at" && argidx
+2 < args
.size()) {
867 int timestep
= atoi(args
[++argidx
].c_str());
868 unsets_at
[timestep
].push_back(args
[++argidx
]);
871 if (args
[argidx
] == "-set-def-at" && argidx
+2 < args
.size()) {
872 int timestep
= atoi(args
[++argidx
].c_str());
873 sets_def_at
[timestep
].push_back(args
[++argidx
]);
877 if (args
[argidx
] == "-set-any-undef-at" && argidx
+2 < args
.size()) {
878 int timestep
= atoi(args
[++argidx
].c_str());
879 sets_any_undef_at
[timestep
].push_back(args
[++argidx
]);
883 if (args
[argidx
] == "-set-all-undef-at" && argidx
+2 < args
.size()) {
884 int timestep
= atoi(args
[++argidx
].c_str());
885 sets_all_undef_at
[timestep
].push_back(args
[++argidx
]);
889 if (args
[argidx
] == "-set-init" && argidx
+2 < args
.size()) {
890 std::string lhs
= args
[++argidx
];
891 std::string rhs
= args
[++argidx
];
892 sets_init
.push_back(std::pair
<std::string
, std::string
>(lhs
, rhs
));
895 if (args
[argidx
] == "-set-init-undef") {
896 set_init_undef
= true;
900 if (args
[argidx
] == "-show" && argidx
+1 < args
.size()) {
901 shows
.push_back(args
[++argidx
]);
904 if (args
[argidx
] == "-show-inputs") {
908 if (args
[argidx
] == "-show-outputs") {
914 extra_args(args
, argidx
, design
);
916 RTLIL::Module
*module
= NULL
;
917 for (auto &mod_it
: design
->modules
)
918 if (design
->selected(mod_it
.second
)) {
920 log_cmd_error("Only one module must be selected for the SAT pass! (selected: %s and %s)\n",
921 RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(mod_it
.first
));
922 module
= mod_it
.second
;
925 log_cmd_error("Can't perform SAT on an empty selection!\n");
927 if (!prove
.size() && !prove_x
.size() && !prove_asserts
&& verify
)
928 log_cmd_error("Got -verify but nothing to prove!\n");
930 if (!prove
.size() && !prove_x
.size() && !prove_asserts
&& tempinduct
)
931 log_cmd_error("Got -tempinduct but nothing to prove!\n");
933 if (seq_len
== 0 && tempinduct
)
934 log_cmd_error("Got -tempinduct but no -seq argument!\n");
936 if (set_def_inputs
) {
937 for (auto &it
: module
->wires
)
938 if (it
.second
->port_input
)
939 sets_def
.push_back(it
.second
->name
);
943 for (auto &it
: module
->wires
)
944 if (it
.second
->port_input
)
945 shows
.push_back(it
.second
->name
);
949 for (auto &it
: module
->wires
)
950 if (it
.second
->port_output
)
951 shows
.push_back(it
.second
->name
);
956 if (loopcount
> 0 || max_undef
)
957 log_cmd_error("The options -max, -all, and -max_undef are not supported for temporal induction proofs!\n");
959 SatHelper
basecase(design
, module
, enable_undef
);
960 SatHelper
inductstep(design
, module
, enable_undef
);
962 basecase
.sets
= sets
;
963 basecase
.prove
= prove
;
964 basecase
.prove_x
= prove_x
;
965 basecase
.prove_asserts
= prove_asserts
;
966 basecase
.sets_at
= sets_at
;
967 basecase
.unsets_at
= unsets_at
;
968 basecase
.shows
= shows
;
969 basecase
.timeout
= timeout
;
970 basecase
.sets_def
= sets_def
;
971 basecase
.sets_any_undef
= sets_any_undef
;
972 basecase
.sets_all_undef
= sets_all_undef
;
973 basecase
.sets_def_at
= sets_def_at
;
974 basecase
.sets_any_undef_at
= sets_any_undef_at
;
975 basecase
.sets_all_undef_at
= sets_all_undef_at
;
976 basecase
.sets_init
= sets_init
;
977 basecase
.set_init_undef
= set_init_undef
;
978 basecase
.satgen
.ignore_div_by_zero
= ignore_div_by_zero
;
980 for (int timestep
= 1; timestep
<= seq_len
; timestep
++)
981 basecase
.setup(timestep
);
982 basecase
.setup_init();
984 inductstep
.sets
= sets
;
985 inductstep
.prove
= prove
;
986 inductstep
.prove_x
= prove_x
;
987 inductstep
.prove_asserts
= prove_asserts
;
988 inductstep
.shows
= shows
;
989 inductstep
.timeout
= timeout
;
990 inductstep
.sets_def
= sets_def
;
991 inductstep
.sets_any_undef
= sets_any_undef
;
992 inductstep
.sets_all_undef
= sets_all_undef
;
993 inductstep
.satgen
.ignore_div_by_zero
= ignore_div_by_zero
;
996 inductstep
.ez
.assume(inductstep
.setup_proof(1));
998 for (int inductlen
= 1; inductlen
<= maxsteps
|| maxsteps
== 0; inductlen
++)
1000 log("\n** Trying induction with length %d **\n", inductlen
);
1002 // phase 1: proving base case
1004 basecase
.setup(seq_len
+ inductlen
);
1005 int property
= basecase
.setup_proof(seq_len
+ inductlen
);
1006 basecase
.generate_model();
1009 basecase
.force_unique_state(seq_len
+ 1, seq_len
+ inductlen
);
1011 log("\n[base case] Solving problem with %d variables and %d clauses..\n",
1012 basecase
.ez
.numCnfVariables(), basecase
.ez
.numCnfClauses());
1014 if (basecase
.solve(basecase
.ez
.NOT(property
))) {
1015 log("SAT temporal induction proof finished - model found for base case: FAIL!\n");
1016 print_proof_failed();
1017 basecase
.print_model();
1021 if (basecase
.gotTimeout
)
1024 log("Base case for induction length %d proven.\n", inductlen
);
1025 basecase
.ez
.assume(property
);
1027 // phase 2: proving induction step
1029 inductstep
.setup(inductlen
+ 1);
1030 property
= inductstep
.setup_proof(inductlen
+ 1);
1031 inductstep
.generate_model();
1034 inductstep
.force_unique_state(1, inductlen
+ 1);
1036 log("\n[induction step] Solving problem with %d variables and %d clauses..\n",
1037 inductstep
.ez
.numCnfVariables(), inductstep
.ez
.numCnfClauses());
1039 if (!inductstep
.solve(inductstep
.ez
.NOT(property
))) {
1040 if (inductstep
.gotTimeout
)
1042 log("Induction step proven: SUCCESS!\n");
1047 log("Induction step failed. Incrementing induction length.\n");
1048 inductstep
.ez
.assume(property
);
1050 inductstep
.print_model();
1053 log("\nReached maximum number of time steps -> proof failed.\n");
1054 print_proof_failed();
1059 log_error("Called with -verify and proof did fail!\n");
1067 log_cmd_error("The options -maxsteps is only supported for temporal induction proofs!\n");
1069 SatHelper
sathelper(design
, module
, enable_undef
);
1071 sathelper
.sets
= sets
;
1072 sathelper
.prove
= prove
;
1073 sathelper
.prove_x
= prove_x
;
1074 sathelper
.prove_asserts
= prove_asserts
;
1075 sathelper
.sets_at
= sets_at
;
1076 sathelper
.unsets_at
= unsets_at
;
1077 sathelper
.shows
= shows
;
1078 sathelper
.timeout
= timeout
;
1079 sathelper
.sets_def
= sets_def
;
1080 sathelper
.sets_any_undef
= sets_any_undef
;
1081 sathelper
.sets_all_undef
= sets_all_undef
;
1082 sathelper
.sets_def_at
= sets_def_at
;
1083 sathelper
.sets_any_undef_at
= sets_any_undef_at
;
1084 sathelper
.sets_all_undef_at
= sets_all_undef_at
;
1085 sathelper
.sets_init
= sets_init
;
1086 sathelper
.set_init_undef
= set_init_undef
;
1087 sathelper
.satgen
.ignore_div_by_zero
= ignore_div_by_zero
;
1091 if (sathelper
.prove
.size() || sathelper
.prove_x
.size() || sathelper
.prove_asserts
)
1092 sathelper
.ez
.assume(sathelper
.ez
.NOT(sathelper
.setup_proof()));
1094 for (int timestep
= 1; timestep
<= seq_len
; timestep
++) {
1095 sathelper
.setup(timestep
);
1096 if (sathelper
.prove
.size() || sathelper
.prove_x
.size() || sathelper
.prove_asserts
)
1097 sathelper
.ez
.assume(sathelper
.ez
.NOT(sathelper
.setup_proof(timestep
)));
1099 sathelper
.setup_init();
1101 sathelper
.generate_model();
1104 // print CNF for debugging
1105 sathelper
.ez
.printDIMACS(stdout
, true);
1108 int rerun_counter
= 0;
1111 log("\nSolving problem with %d variables and %d clauses..\n",
1112 sathelper
.ez
.numCnfVariables(), sathelper
.ez
.numCnfClauses());
1114 if (sathelper
.solve())
1117 log("SAT model found. maximizing number of undefs.\n");
1118 sathelper
.maximize_undefs();
1121 if (!prove
.size() && !prove_x
.size() && !prove_asserts
) {
1122 log("SAT solving finished - model found:\n");
1124 log("SAT proof finished - model found: FAIL!\n");
1125 print_proof_failed();
1128 sathelper
.print_model();
1130 if (loopcount
!= 0) {
1131 loopcount
--, rerun_counter
++;
1132 sathelper
.invalidate_model(max_undef
);
1138 log_error("Called with -verify and proof did fail!\n");
1143 if (sathelper
.gotTimeout
)
1146 log("SAT solving finished - no more models found (after %d distinct solutions).\n", rerun_counter
);
1147 else if (!prove
.size() && !prove_x
.size() && !prove_asserts
)
1148 log("SAT solving finished - no model found.\n");
1150 log("SAT proof finished - no model found: SUCCESS!\n");
1155 if (verify
&& rerun_counter
) {
1157 log_error("Called with -verify and proof did fail!\n");
1163 log("Interrupted SAT solver: TIMEOUT!\n");
1165 if (fail_on_timeout
)
1166 log_error("Called with -verify and proof did time out!\n");