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"
40 RTLIL::Design
*design
;
41 RTLIL::Module
*module
;
48 // additional constraints
49 std::vector
<std::pair
<std::string
, std::string
>> sets
, prove
, prove_x
, sets_init
;
50 std::map
<int, std::vector
<std::pair
<std::string
, std::string
>>> sets_at
;
51 std::map
<int, std::vector
<std::string
>> unsets_at
;
55 bool enable_undef
, set_init_def
, set_init_undef
, set_init_zero
, ignore_unknown_cells
;
56 std::vector
<std::string
> sets_def
, sets_any_undef
, sets_all_undef
;
57 std::map
<int, std::vector
<std::string
>> sets_def_at
, sets_any_undef_at
, sets_all_undef_at
;
60 std::vector
<std::string
> shows
;
61 SigPool show_signal_pool
;
62 SigSet
<RTLIL::Cell
*> show_drivers
;
63 int max_timestep
, timeout
;
66 SatHelper(RTLIL::Design
*design
, RTLIL::Module
*module
, bool enable_undef
) :
67 design(design
), module(module
), sigmap(module
), ct(design
), satgen(&ez
, &sigmap
)
69 this->enable_undef
= enable_undef
;
70 satgen
.model_undef
= enable_undef
;
72 set_init_undef
= false;
73 set_init_zero
= false;
74 ignore_unknown_cells
= false;
80 void check_undef_enabled(const RTLIL::SigSpec
&sig
)
85 std::vector
<RTLIL::SigBit
> sigbits
= sig
.to_sigbit_vector();
86 for (size_t i
= 0; i
< sigbits
.size(); i
++)
87 if (sigbits
[i
].wire
== NULL
&& sigbits
[i
].data
== RTLIL::State::Sx
)
88 log_cmd_error("Bit %d of %s is undef but option -enable_undef is missing!\n", int(i
), log_signal(sig
));
93 log ("\nSetting up initial state:\n");
95 RTLIL::SigSpec big_lhs
, big_rhs
;
97 for (auto &it
: module
->wires
)
99 if (it
.second
->attributes
.count("\\init") == 0)
102 RTLIL::SigSpec lhs
= sigmap(it
.second
);
103 RTLIL::SigSpec rhs
= it
.second
->attributes
.at("\\init");
104 log_assert(lhs
.size() == rhs
.size());
106 RTLIL::SigSpec removed_bits
;
107 for (int i
= 0; i
< lhs
.size(); i
++) {
108 RTLIL::SigSpec bit
= lhs
.extract(i
, 1);
109 if (!satgen
.initial_state
.check_all(bit
)) {
110 removed_bits
.append(bit
);
117 if (removed_bits
.size())
118 log("Warning: ignoring initial value on non-register: %s\n", log_signal(removed_bits
));
121 log("Import set-constraint from init attribute: %s = %s\n", log_signal(lhs
), log_signal(rhs
));
122 big_lhs
.remove2(lhs
, &big_rhs
);
128 for (auto &s
: sets_init
)
130 RTLIL::SigSpec lhs
, rhs
;
132 if (!RTLIL::SigSpec::parse_sel(lhs
, design
, module
, s
.first
))
133 log_cmd_error("Failed to parse lhs set expression `%s'.\n", s
.first
.c_str());
134 if (!RTLIL::SigSpec::parse_rhs(lhs
, rhs
, module
, s
.second
))
135 log_cmd_error("Failed to parse rhs set expression `%s'.\n", s
.second
.c_str());
136 show_signal_pool
.add(sigmap(lhs
));
137 show_signal_pool
.add(sigmap(rhs
));
139 if (lhs
.size() != rhs
.size())
140 log_cmd_error("Set expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
141 s
.first
.c_str(), log_signal(lhs
), lhs
.size(), s
.second
.c_str(), log_signal(rhs
), rhs
.size());
143 log("Import set-constraint: %s = %s\n", log_signal(lhs
), log_signal(rhs
));
144 big_lhs
.remove2(lhs
, &big_rhs
);
149 if (!satgen
.initial_state
.check_all(big_lhs
)) {
150 RTLIL::SigSpec rem
= satgen
.initial_state
.remove(big_lhs
);
151 log_cmd_error("Found -set-init bits that are not part of the initial_state: %s\n", log_signal(rem
));
155 RTLIL::SigSpec rem
= satgen
.initial_state
.export_all();
156 std::vector
<int> undef_rem
= satgen
.importUndefSigSpec(rem
, 1);
157 ez
.assume(ez
.NOT(ez
.expression(ezSAT::OpOr
, undef_rem
)));
160 if (set_init_undef
) {
161 RTLIL::SigSpec rem
= satgen
.initial_state
.export_all();
164 big_rhs
.append(RTLIL::SigSpec(RTLIL::State::Sx
, rem
.size()));
168 RTLIL::SigSpec rem
= satgen
.initial_state
.export_all();
171 big_rhs
.append(RTLIL::SigSpec(RTLIL::State::S0
, rem
.size()));
174 if (big_lhs
.size() == 0) {
175 log("No constraints for initial state found.\n\n");
179 log("Final constraint equation: %s = %s\n\n", log_signal(big_lhs
), log_signal(big_rhs
));
180 check_undef_enabled(big_lhs
), check_undef_enabled(big_rhs
);
181 ez
.assume(satgen
.signals_eq(big_lhs
, big_rhs
, 1));
184 void setup(int timestep
= -1)
187 log ("\nSetting up time step %d:\n", timestep
);
189 log ("\nSetting up SAT problem:\n");
191 if (timestep
> max_timestep
)
192 max_timestep
= timestep
;
194 RTLIL::SigSpec big_lhs
, big_rhs
;
198 RTLIL::SigSpec lhs
, rhs
;
200 if (!RTLIL::SigSpec::parse_sel(lhs
, design
, module
, s
.first
))
201 log_cmd_error("Failed to parse lhs set expression `%s'.\n", s
.first
.c_str());
202 if (!RTLIL::SigSpec::parse_rhs(lhs
, rhs
, module
, s
.second
))
203 log_cmd_error("Failed to parse rhs set expression `%s'.\n", s
.second
.c_str());
204 show_signal_pool
.add(sigmap(lhs
));
205 show_signal_pool
.add(sigmap(rhs
));
207 if (lhs
.size() != rhs
.size())
208 log_cmd_error("Set expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
209 s
.first
.c_str(), log_signal(lhs
), lhs
.size(), s
.second
.c_str(), log_signal(rhs
), rhs
.size());
211 log("Import set-constraint: %s = %s\n", log_signal(lhs
), log_signal(rhs
));
212 big_lhs
.remove2(lhs
, &big_rhs
);
217 for (auto &s
: sets_at
[timestep
])
219 RTLIL::SigSpec lhs
, rhs
;
221 if (!RTLIL::SigSpec::parse_sel(lhs
, design
, module
, s
.first
))
222 log_cmd_error("Failed to parse lhs set expression `%s'.\n", s
.first
.c_str());
223 if (!RTLIL::SigSpec::parse_rhs(lhs
, rhs
, module
, s
.second
))
224 log_cmd_error("Failed to parse rhs set expression `%s'.\n", s
.second
.c_str());
225 show_signal_pool
.add(sigmap(lhs
));
226 show_signal_pool
.add(sigmap(rhs
));
228 if (lhs
.size() != rhs
.size())
229 log_cmd_error("Set expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
230 s
.first
.c_str(), log_signal(lhs
), lhs
.size(), s
.second
.c_str(), log_signal(rhs
), rhs
.size());
232 log("Import set-constraint for this timestep: %s = %s\n", log_signal(lhs
), log_signal(rhs
));
233 big_lhs
.remove2(lhs
, &big_rhs
);
238 for (auto &s
: unsets_at
[timestep
])
242 if (!RTLIL::SigSpec::parse_sel(lhs
, design
, module
, s
))
243 log_cmd_error("Failed to parse lhs set expression `%s'.\n", s
.c_str());
244 show_signal_pool
.add(sigmap(lhs
));
246 log("Import unset-constraint for this timestep: %s\n", log_signal(lhs
));
247 big_lhs
.remove2(lhs
, &big_rhs
);
250 log("Final constraint equation: %s = %s\n", log_signal(big_lhs
), log_signal(big_rhs
));
251 check_undef_enabled(big_lhs
), check_undef_enabled(big_rhs
);
252 ez
.assume(satgen
.signals_eq(big_lhs
, big_rhs
, timestep
));
255 // 1 = sets_any_undef
256 // 2 = sets_all_undef
257 std::set
<RTLIL::SigSpec
> sets_def_undef
[3];
259 for (auto &s
: sets_def
) {
261 if (!RTLIL::SigSpec::parse_sel(sig
, design
, module
, s
))
262 log_cmd_error("Failed to parse set-def expression `%s'.\n", s
.c_str());
263 sets_def_undef
[0].insert(sig
);
266 for (auto &s
: sets_any_undef
) {
268 if (!RTLIL::SigSpec::parse_sel(sig
, design
, module
, s
))
269 log_cmd_error("Failed to parse set-def expression `%s'.\n", s
.c_str());
270 sets_def_undef
[1].insert(sig
);
273 for (auto &s
: sets_all_undef
) {
275 if (!RTLIL::SigSpec::parse_sel(sig
, design
, module
, s
))
276 log_cmd_error("Failed to parse set-def expression `%s'.\n", s
.c_str());
277 sets_def_undef
[2].insert(sig
);
280 for (auto &s
: sets_def_at
[timestep
]) {
282 if (!RTLIL::SigSpec::parse_sel(sig
, design
, module
, s
))
283 log_cmd_error("Failed to parse set-def expression `%s'.\n", s
.c_str());
284 sets_def_undef
[0].insert(sig
);
285 sets_def_undef
[1].erase(sig
);
286 sets_def_undef
[2].erase(sig
);
289 for (auto &s
: sets_any_undef_at
[timestep
]) {
291 if (!RTLIL::SigSpec::parse_sel(sig
, design
, module
, s
))
292 log_cmd_error("Failed to parse set-def expression `%s'.\n", s
.c_str());
293 sets_def_undef
[0].erase(sig
);
294 sets_def_undef
[1].insert(sig
);
295 sets_def_undef
[2].erase(sig
);
298 for (auto &s
: sets_all_undef_at
[timestep
]) {
300 if (!RTLIL::SigSpec::parse_sel(sig
, design
, module
, s
))
301 log_cmd_error("Failed to parse set-def expression `%s'.\n", s
.c_str());
302 sets_def_undef
[0].erase(sig
);
303 sets_def_undef
[1].erase(sig
);
304 sets_def_undef
[2].insert(sig
);
307 for (int t
= 0; t
< 3; t
++)
308 for (auto &sig
: sets_def_undef
[t
]) {
309 log("Import %s constraint for this timestep: %s\n", t
== 0 ? "def" : t
== 1 ? "any_undef" : "all_undef", log_signal(sig
));
310 std::vector
<int> undef_sig
= satgen
.importUndefSigSpec(sig
, timestep
);
312 ez
.assume(ez
.NOT(ez
.expression(ezSAT::OpOr
, undef_sig
)));
314 ez
.assume(ez
.expression(ezSAT::OpOr
, undef_sig
));
316 ez
.assume(ez
.expression(ezSAT::OpAnd
, undef_sig
));
319 int import_cell_counter
= 0;
320 for (auto &c
: module
->cells
)
321 if (design
->selected(module
, c
.second
)) {
322 // log("Import cell: %s\n", RTLIL::id2cstr(c.first));
323 if (satgen
.importCell(c
.second
, timestep
)) {
324 for (auto &p
: c
.second
->connections_
)
325 if (ct
.cell_output(c
.second
->type
, p
.first
))
326 show_drivers
.insert(sigmap(p
.second
), c
.second
);
327 import_cell_counter
++;
328 } else if (ignore_unknown_cells
)
329 log("Warning: Failed to import cell %s (type %s) to SAT database.\n", RTLIL::id2cstr(c
.first
), RTLIL::id2cstr(c
.second
->type
));
331 log_error("Failed to import cell %s (type %s) to SAT database.\n", RTLIL::id2cstr(c
.first
), RTLIL::id2cstr(c
.second
->type
));
333 log("Imported %d cells to SAT database.\n", import_cell_counter
);
336 int setup_proof(int timestep
= -1)
338 assert(prove
.size() || prove_x
.size() || prove_asserts
);
340 RTLIL::SigSpec big_lhs
, big_rhs
;
341 std::vector
<int> prove_bits
;
343 if (prove
.size() > 0)
345 for (auto &s
: prove
)
347 RTLIL::SigSpec lhs
, rhs
;
349 if (!RTLIL::SigSpec::parse_sel(lhs
, design
, module
, s
.first
))
350 log_cmd_error("Failed to parse lhs proof expression `%s'.\n", s
.first
.c_str());
351 if (!RTLIL::SigSpec::parse_rhs(lhs
, rhs
, module
, s
.second
))
352 log_cmd_error("Failed to parse rhs proof expression `%s'.\n", s
.second
.c_str());
353 show_signal_pool
.add(sigmap(lhs
));
354 show_signal_pool
.add(sigmap(rhs
));
356 if (lhs
.size() != rhs
.size())
357 log_cmd_error("Proof expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
358 s
.first
.c_str(), log_signal(lhs
), lhs
.size(), s
.second
.c_str(), log_signal(rhs
), rhs
.size());
360 log("Import proof-constraint: %s = %s\n", log_signal(lhs
), log_signal(rhs
));
361 big_lhs
.remove2(lhs
, &big_rhs
);
366 log("Final proof equation: %s = %s\n", log_signal(big_lhs
), log_signal(big_rhs
));
367 check_undef_enabled(big_lhs
), check_undef_enabled(big_rhs
);
368 prove_bits
.push_back(satgen
.signals_eq(big_lhs
, big_rhs
, timestep
));
371 if (prove_x
.size() > 0)
373 for (auto &s
: prove_x
)
375 RTLIL::SigSpec lhs
, rhs
;
377 if (!RTLIL::SigSpec::parse_sel(lhs
, design
, module
, s
.first
))
378 log_cmd_error("Failed to parse lhs proof-x expression `%s'.\n", s
.first
.c_str());
379 if (!RTLIL::SigSpec::parse_rhs(lhs
, rhs
, module
, s
.second
))
380 log_cmd_error("Failed to parse rhs proof-x expression `%s'.\n", s
.second
.c_str());
381 show_signal_pool
.add(sigmap(lhs
));
382 show_signal_pool
.add(sigmap(rhs
));
384 if (lhs
.size() != rhs
.size())
385 log_cmd_error("Proof-x expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
386 s
.first
.c_str(), log_signal(lhs
), lhs
.size(), s
.second
.c_str(), log_signal(rhs
), rhs
.size());
388 log("Import proof-x-constraint: %s = %s\n", log_signal(lhs
), log_signal(rhs
));
389 big_lhs
.remove2(lhs
, &big_rhs
);
394 log("Final proof-x equation: %s = %s\n", log_signal(big_lhs
), log_signal(big_rhs
));
396 std::vector
<int> value_lhs
= satgen
.importDefSigSpec(big_lhs
, timestep
);
397 std::vector
<int> value_rhs
= satgen
.importDefSigSpec(big_rhs
, timestep
);
399 std::vector
<int> undef_lhs
= satgen
.importUndefSigSpec(big_lhs
, timestep
);
400 std::vector
<int> undef_rhs
= satgen
.importUndefSigSpec(big_rhs
, timestep
);
402 for (size_t i
= 0; i
< value_lhs
.size(); i
++)
403 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
))))));
407 RTLIL::SigSpec asserts_a
, asserts_en
;
408 satgen
.getAsserts(asserts_a
, asserts_en
, timestep
);
409 for (int i
= 0; i
< SIZE(asserts_a
); i
++)
410 log("Import proof for assert: %s when %s.\n", log_signal(asserts_a
[i
]), log_signal(asserts_en
[i
]));
411 prove_bits
.push_back(satgen
.importAsserts(timestep
));
414 return ez
.expression(ezSAT::OpAnd
, prove_bits
);
417 void force_unique_state(int timestep_from
, int timestep_to
)
419 RTLIL::SigSpec state_signals
= satgen
.initial_state
.export_all();
420 for (int i
= timestep_from
; i
< timestep_to
; i
++)
421 ez
.assume(ez
.NOT(satgen
.signals_eq(state_signals
, state_signals
, i
, timestep_to
)));
424 bool solve(const std::vector
<int> &assumptions
)
426 log_assert(gotTimeout
== false);
427 ez
.setSolverTimeout(timeout
);
428 bool success
= ez
.solve(modelExpressions
, modelValues
, assumptions
);
429 if (ez
.getSolverTimoutStatus())
434 bool solve(int a
= 0, int b
= 0, int c
= 0, int d
= 0, int e
= 0, int f
= 0)
436 log_assert(gotTimeout
== false);
437 ez
.setSolverTimeout(timeout
);
438 bool success
= ez
.solve(modelExpressions
, modelValues
, a
, b
, c
, d
, e
, f
);
439 if (ez
.getSolverTimoutStatus())
444 struct ModelBlockInfo
{
445 int timestep
, offset
, width
;
446 std::string description
;
447 bool operator < (const ModelBlockInfo
&other
) const {
448 if (timestep
!= other
.timestep
)
449 return timestep
< other
.timestep
;
450 if (description
!= other
.description
)
451 return description
< other
.description
;
452 if (offset
!= other
.offset
)
453 return offset
< other
.offset
;
454 if (width
!= other
.width
)
455 return width
< other
.width
;
460 std::vector
<int> modelExpressions
;
461 std::vector
<bool> modelValues
;
462 std::set
<ModelBlockInfo
> modelInfo
;
464 void maximize_undefs()
466 log_assert(enable_undef
);
467 std::vector
<bool> backupValues
;
471 std::vector
<int> must_undef
, maybe_undef
;
473 for (size_t i
= 0; i
< modelExpressions
.size()/2; i
++)
474 if (modelValues
.at(modelExpressions
.size()/2 + i
))
475 must_undef
.push_back(modelExpressions
.at(modelExpressions
.size()/2 + i
));
477 maybe_undef
.push_back(modelExpressions
.at(modelExpressions
.size()/2 + i
));
479 backupValues
.swap(modelValues
);
480 if (!solve(ez
.expression(ezSAT::OpAnd
, must_undef
), ez
.expression(ezSAT::OpOr
, maybe_undef
)))
484 backupValues
.swap(modelValues
);
487 void generate_model()
489 RTLIL::SigSpec modelSig
;
490 modelExpressions
.clear();
493 // Add "show" signals or alternatively the leaves on the input cone on all set and prove signals
495 if (shows
.size() == 0)
497 SigPool queued_signals
, handled_signals
, final_signals
;
498 queued_signals
= show_signal_pool
;
499 while (queued_signals
.size() > 0) {
500 RTLIL::SigSpec sig
= queued_signals
.export_one();
501 queued_signals
.del(sig
);
502 handled_signals
.add(sig
);
503 std::set
<RTLIL::Cell
*> drivers
= show_drivers
.find(sig
);
504 if (drivers
.size() == 0) {
505 final_signals
.add(sig
);
507 for (auto &d
: drivers
)
508 for (auto &p
: d
->connections_
) {
509 if (d
->type
== "$dff" && p
.first
== "\\CLK")
511 if (d
->type
.substr(0, 6) == "$_DFF_" && p
.first
== "\\C")
513 queued_signals
.add(handled_signals
.remove(sigmap(p
.second
)));
517 modelSig
= final_signals
.export_all();
519 // additionally add all set and prove signals directly
520 // (it improves user confidence if we write the constraints back ;-)
521 modelSig
.append(show_signal_pool
.export_all());
525 for (auto &s
: shows
) {
527 if (!RTLIL::SigSpec::parse_sel(sig
, design
, module
, s
))
528 log_cmd_error("Failed to parse show expression `%s'.\n", s
.c_str());
529 log("Import show expression: %s\n", log_signal(sig
));
530 modelSig
.append(sig
);
534 modelSig
.sort_and_unify();
535 // log("Model signals: %s\n", log_signal(modelSig));
537 std::vector
<int> modelUndefExpressions
;
539 for (auto &c
: modelSig
.chunks())
543 RTLIL::SigSpec chunksig
= c
;
544 info
.width
= chunksig
.size();
545 info
.description
= log_signal(chunksig
);
547 for (int timestep
= -1; timestep
<= max_timestep
; timestep
++)
549 if ((timestep
== -1 && max_timestep
> 0) || timestep
== 0)
552 info
.timestep
= timestep
;
553 info
.offset
= modelExpressions
.size();
554 modelInfo
.insert(info
);
556 std::vector
<int> vec
= satgen
.importSigSpec(chunksig
, timestep
);
557 modelExpressions
.insert(modelExpressions
.end(), vec
.begin(), vec
.end());
560 std::vector
<int> undef_vec
= satgen
.importUndefSigSpec(chunksig
, timestep
);
561 modelUndefExpressions
.insert(modelUndefExpressions
.end(), undef_vec
.begin(), undef_vec
.end());
566 // Add initial state signals as collected by satgen
568 modelSig
= satgen
.initial_state
.export_all();
569 for (auto &c
: modelSig
.chunks())
573 RTLIL::SigSpec chunksig
= c
;
576 info
.offset
= modelExpressions
.size();
577 info
.width
= chunksig
.size();
578 info
.description
= log_signal(chunksig
);
579 modelInfo
.insert(info
);
581 std::vector
<int> vec
= satgen
.importSigSpec(chunksig
, 1);
582 modelExpressions
.insert(modelExpressions
.end(), vec
.begin(), vec
.end());
585 std::vector
<int> undef_vec
= satgen
.importUndefSigSpec(chunksig
, 1);
586 modelUndefExpressions
.insert(modelUndefExpressions
.end(), undef_vec
.begin(), undef_vec
.end());
590 modelExpressions
.insert(modelExpressions
.end(), modelUndefExpressions
.begin(), modelUndefExpressions
.end());
595 int maxModelName
= 10;
596 int maxModelWidth
= 10;
598 for (auto &info
: modelInfo
) {
599 maxModelName
= std::max(maxModelName
, int(info
.description
.size()));
600 maxModelWidth
= std::max(maxModelWidth
, info
.width
);
605 int last_timestep
= -2;
606 for (auto &info
: modelInfo
)
609 bool found_undef
= false;
611 for (int i
= 0; i
< info
.width
; i
++) {
612 value
.bits
.push_back(modelValues
.at(info
.offset
+i
) ? RTLIL::State::S1
: RTLIL::State::S0
);
613 if (enable_undef
&& modelValues
.at(modelExpressions
.size()/2 + info
.offset
+ i
))
614 value
.bits
.back() = RTLIL::State::Sx
, found_undef
= true;
617 if (info
.timestep
!= last_timestep
) {
618 const char *hline
= "---------------------------------------------------------------------------------------------------"
619 "---------------------------------------------------------------------------------------------------"
620 "---------------------------------------------------------------------------------------------------";
621 if (last_timestep
== -2) {
622 log(max_timestep
> 0 ? " Time " : " ");
623 log("%-*s %10s %10s %*s\n", maxModelName
+10, "Signal Name", "Dec", "Hex", maxModelWidth
+5, "Bin");
625 log(max_timestep
> 0 ? " ---- " : " ");
626 log("%*.*s %10.10s %10.10s %*.*s\n", maxModelName
+10, maxModelName
+10,
627 hline
, hline
, hline
, maxModelWidth
+5, maxModelWidth
+5, hline
);
628 last_timestep
= info
.timestep
;
631 if (max_timestep
> 0) {
632 if (info
.timestep
> 0)
633 log(" %4d ", info
.timestep
);
639 if (info
.width
<= 32 && !found_undef
)
640 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 log("%-*s %10s %10s %*s\n", maxModelName
+10, info
.description
.c_str(), "--", "--", maxModelWidth
+5, value
.as_string().c_str());
645 if (last_timestep
== -2)
646 log(" no model variables selected for display.\n");
649 void dump_model_to_vcd(std::string vcd_file_name
)
651 FILE *f
= fopen(vcd_file_name
.c_str(), "w");
653 log_cmd_error("Can't open output file `%s' for writing: %s\n", vcd_file_name
.c_str(), strerror(errno
));
655 log("Dumping SAT model to VCD file %s\n", vcd_file_name
.c_str());
659 char stime
[128] = {};
661 now
= localtime(×tamp
);
662 strftime(stime
, sizeof(stime
), "%c", now
);
664 std::string module_fname
= "unknown";
665 auto apos
= module
->attributes
.find("\\src");
666 if(apos
!= module
->attributes
.end())
667 module_fname
= module
->attributes
["\\src"].decode_string();
669 fprintf(f
, "$date\n");
670 fprintf(f
, " %s\n", stime
);
671 fprintf(f
, "$end\n");
672 fprintf(f
, "$version\n");
673 fprintf(f
, " Generated by %s\n", yosys_version_str
);
674 fprintf(f
, "$end\n");
675 fprintf(f
, "$comment\n");
676 fprintf(f
, " Generated from SAT problem in module %s (declared at %s)\n",
677 module
->name
.c_str(), module_fname
.c_str());
678 fprintf(f
, "$end\n");
680 // VCD has some limits on internal (non-display) identifier names, so make legal ones
681 std::map
<std::string
, std::string
> vcdnames
;
683 fprintf(f
, "$timescale 1ns\n"); // arbitrary time scale since actual clock period is unknown/unimportant
684 fprintf(f
, "$scope module %s $end\n", module
->name
.c_str());
685 for (auto &info
: modelInfo
)
687 if (vcdnames
.find(info
.description
) != vcdnames
.end())
691 snprintf(namebuf
, sizeof(namebuf
), "v%d", static_cast<int>(vcdnames
.size()));
692 vcdnames
[info
.description
] = namebuf
;
694 // Even display identifiers can't use some special characters
695 std::string legal_desc
= info
.description
.c_str();
696 for (auto &c
: legal_desc
) {
703 fprintf(f
, "$var wire %d %s %s $end\n", info
.width
, namebuf
, legal_desc
.c_str());
705 // Need to look at first *two* cycles!
706 // We need to put a name on all variables but those without an initialization clause
707 // have no value at timestep 0
708 if(info
.timestep
> 1)
711 fprintf(f
, "$upscope $end\n");
712 fprintf(f
, "$enddefinitions $end\n");
713 fprintf(f
, "$dumpvars\n");
715 static const char bitvals
[] = "01xzxx";
717 int last_timestep
= -2;
718 for (auto &info
: modelInfo
)
722 for (int i
= 0; i
< info
.width
; i
++) {
723 value
.bits
.push_back(modelValues
.at(info
.offset
+i
) ? RTLIL::State::S1
: RTLIL::State::S0
);
724 if (enable_undef
&& modelValues
.at(modelExpressions
.size()/2 + info
.offset
+ i
))
725 value
.bits
.back() = RTLIL::State::Sx
;
728 if (info
.timestep
!= last_timestep
) {
729 if(last_timestep
== 0)
730 fprintf(f
, "$end\n");
732 fprintf(f
, "#%d\n", info
.timestep
);
733 last_timestep
= info
.timestep
;
736 if(info
.width
== 1) {
737 fprintf(f
, "%c%s\n", bitvals
[value
.bits
[0]], vcdnames
[info
.description
].c_str());
740 for(int k
=info
.width
-1; k
>= 0; k
--) //need to flip bit ordering for VCD
741 fprintf(f
, "%c", bitvals
[value
.bits
[k
]]);
742 fprintf(f
, " %s\n", vcdnames
[info
.description
].c_str());
746 if (last_timestep
== -2)
747 log(" no model variables selected for display.\n");
752 void invalidate_model(bool max_undef
)
754 std::vector
<int> clause
;
756 for (size_t i
= 0; i
< modelExpressions
.size()/2; i
++) {
757 int bit
= modelExpressions
.at(i
), bit_undef
= modelExpressions
.at(modelExpressions
.size()/2 + i
);
758 bool val
= modelValues
.at(i
), val_undef
= modelValues
.at(modelExpressions
.size()/2 + i
);
759 if (!max_undef
|| !val_undef
)
760 clause
.push_back(val_undef
? ez
.NOT(bit_undef
) : val
? ez
.NOT(bit
) : bit
);
763 for (size_t i
= 0; i
< modelExpressions
.size(); i
++)
764 clause
.push_back(modelValues
.at(i
) ? ez
.NOT(modelExpressions
.at(i
)) : modelExpressions
.at(i
));
765 ez
.assume(ez
.expression(ezSAT::OpOr
, clause
));
771 static void print_proof_failed()
774 log(" ______ ___ ___ _ _ _ _ \n");
775 log(" (_____ \\ / __) / __) (_) | | | |\n");
776 log(" _____) )___ ___ ___ _| |__ _| |__ _____ _| | _____ __| | |\n");
777 log(" | ____/ ___) _ \\ / _ (_ __) (_ __|____ | | || ___ |/ _ |_|\n");
778 log(" | | | | | |_| | |_| || | | | / ___ | | || ____( (_| |_ \n");
779 log(" |_| |_| \\___/ \\___/ |_| |_| \\_____|_|\\_)_____)\\____|_|\n");
783 static void print_timeout()
786 log(" _____ _ _ _____ ____ _ _____\n");
787 log(" /__ __\\/ \\/ \\__/|/ __// _ \\/ \\ /\\/__ __\\\n");
788 log(" / \\ | || |\\/||| \\ | / \\|| | || / \\\n");
789 log(" | | | || | ||| /_ | \\_/|| \\_/| | |\n");
790 log(" \\_/ \\_/\\_/ \\|\\____\\\\____/\\____/ \\_/\n");
794 static void print_qed()
797 log(" /$$$$$$ /$$$$$$$$ /$$$$$$$ \n");
798 log(" /$$__ $$ | $$_____/ | $$__ $$ \n");
799 log(" | $$ \\ $$ | $$ | $$ \\ $$ \n");
800 log(" | $$ | $$ | $$$$$ | $$ | $$ \n");
801 log(" | $$ | $$ | $$__/ | $$ | $$ \n");
802 log(" | $$/$$ $$ | $$ | $$ | $$ \n");
803 log(" | $$$$$$/ /$$| $$$$$$$$ /$$| $$$$$$$//$$\n");
804 log(" \\____ $$$|__/|________/|__/|_______/|__/\n");
809 struct SatPass
: public Pass
{
810 SatPass() : Pass("sat", "solve a SAT problem in the circuit") { }
813 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
815 log(" sat [options] [selection]\n");
817 log("This command solves a SAT problem defined over the currently selected circuit\n");
818 log("and additional constraints passed as parameters.\n");
821 log(" show all solutions to the problem (this can grow exponentially, use\n");
822 log(" -max <N> instead to get <N> solutions)\n");
825 log(" like -all, but limit number of solutions to <N>\n");
827 log(" -enable_undef\n");
828 log(" enable modeling of undef value (aka 'x-bits')\n");
829 log(" this option is implied by -set-def, -set-undef et. cetera\n");
831 log(" -max_undef\n");
832 log(" maximize the number of undef bits in solutions, giving a better\n");
833 log(" picture of which input bits are actually vital to the solution.\n");
835 log(" -set <signal> <value>\n");
836 log(" set the specified signal to the specified value.\n");
838 log(" -set-def <signal>\n");
839 log(" add a constraint that all bits of the given signal must be defined\n");
841 log(" -set-any-undef <signal>\n");
842 log(" add a constraint that at least one bit of the given signal is undefined\n");
844 log(" -set-all-undef <signal>\n");
845 log(" add a constraint that all bits of the given signal are undefined\n");
847 log(" -set-def-inputs\n");
848 log(" add -set-def constraints for all module inputs\n");
850 log(" -show <signal>\n");
851 log(" show the model for the specified signal. if no -show option is\n");
852 log(" passed then a set of signals to be shown is automatically selected.\n");
854 log(" -show-inputs, -show-outputs\n");
855 log(" add all module input (output) ports to the list of shown signals\n");
857 log(" -ignore_div_by_zero\n");
858 log(" ignore all solutions that involve a division by zero\n");
860 log(" -ignore_unknown_cells\n");
861 log(" ignore all cells that can not be matched to a SAT model\n");
863 log("The following options can be used to set up a sequential problem:\n");
866 log(" set up a sequential problem with <N> time steps. The steps will\n");
867 log(" be numbered from 1 to N.\n");
869 log(" -set-at <N> <signal> <value>\n");
870 log(" -unset-at <N> <signal>\n");
871 log(" set or unset the specified signal to the specified value in the\n");
872 log(" given timestep. this has priority over a -set for the same signal.\n");
874 log(" -set-def-at <N> <signal>\n");
875 log(" -set-any-undef-at <N> <signal>\n");
876 log(" -set-all-undef-at <N> <signal>\n");
877 log(" add undef contraints in the given timestep.\n");
879 log(" -set-init <signal> <value>\n");
880 log(" set the initial value for the register driving the signal to the value\n");
882 log(" -set-init-undef\n");
883 log(" set all initial states (not set using -set-init) to undef\n");
885 log(" -set-init-def\n");
886 log(" do not force a value for the initial state but do not allow undef\n");
888 log(" -set-init-zero\n");
889 log(" set all initial states (not set using -set-init) to zero\n");
891 log(" -dump_vcd <vcd-file-name>\n");
892 log(" dump SAT model (counter example in proof) to VCD file\n");
894 log(" -dump_cnf <cnf-file-name>\n");
895 log(" dump CNF of SAT problem (in DIMACS format). in temporal induction\n");
896 log(" proofs this is the CNF of the first induction step.\n");
898 log("The following additional options can be used to set up a proof. If also -seq\n");
899 log("is passed, a temporal induction proof is performed.\n");
901 log(" -tempinduct\n");
902 log(" Perform a temporal induction proof. In a temporalinduction proof it is\n");
903 log(" proven that the condition holds forever after the number of time steps\n");
904 log(" specified using -seq.\n");
906 log(" -tempinduct-def\n");
907 log(" Perform a temporal induction proof. Assume an initial state with all\n");
908 log(" registers set to defined values for the induction step.\n");
910 log(" -prove <signal> <value>\n");
911 log(" Attempt to proof that <signal> is always <value>.\n");
913 log(" -prove-x <signal> <value>\n");
914 log(" Like -prove, but an undef (x) bit in the lhs matches any value on\n");
915 log(" the right hand side. Useful for equivialence checking.\n");
917 log(" -prove-asserts\n");
918 log(" Prove that all asserts in the design hold.\n");
920 log(" -maxsteps <N>\n");
921 log(" Set a maximum length for the induction.\n");
923 log(" -initsteps <N>\n");
924 log(" Set initial length for the induction.\n");
926 log(" -timeout <N>\n");
927 log(" Maximum number of seconds a single SAT instance may take.\n");
930 log(" Return an error and stop the synthesis script if the proof fails.\n");
932 log(" -verify-no-timeout\n");
933 log(" Like -verify but do not return an error for timeouts.\n");
936 log(" Return an error and stop the synthesis script if the proof succeeds.\n");
938 log(" -falsify-no-timeout\n");
939 log(" Like -falsify but do not return an error for timeouts.\n");
942 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
944 std::vector
<std::pair
<std::string
, std::string
>> sets
, sets_init
, prove
, prove_x
;
945 std::map
<int, std::vector
<std::pair
<std::string
, std::string
>>> sets_at
;
946 std::map
<int, std::vector
<std::string
>> unsets_at
, sets_def_at
, sets_any_undef_at
, sets_all_undef_at
;
947 std::vector
<std::string
> shows
, sets_def
, sets_any_undef
, sets_all_undef
;
948 int loopcount
= 0, seq_len
= 0, maxsteps
= 0, initsteps
= 0, timeout
= 0;
949 bool verify
= false, fail_on_timeout
= false, enable_undef
= false, set_def_inputs
= false;
950 bool ignore_div_by_zero
= false, set_init_undef
= false, set_init_zero
= false, max_undef
= false;
951 bool tempinduct
= false, prove_asserts
= false, show_inputs
= false, show_outputs
= false;
952 bool ignore_unknown_cells
= false, falsify
= false, tempinduct_def
= false, set_init_def
= false;
953 std::string vcd_file_name
, cnf_file_name
;
955 log_header("Executing SAT pass (solving SAT problems in the circuit).\n");
958 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
959 if (args
[argidx
] == "-all") {
963 if (args
[argidx
] == "-verify") {
964 fail_on_timeout
= true;
968 if (args
[argidx
] == "-verify-no-timeout") {
972 if (args
[argidx
] == "-falsify") {
973 fail_on_timeout
= true;
977 if (args
[argidx
] == "-falsify-no-timeout") {
981 if (args
[argidx
] == "-timeout" && argidx
+1 < args
.size()) {
982 timeout
= atoi(args
[++argidx
].c_str());
985 if (args
[argidx
] == "-max" && argidx
+1 < args
.size()) {
986 loopcount
= atoi(args
[++argidx
].c_str());
989 if (args
[argidx
] == "-maxsteps" && argidx
+1 < args
.size()) {
990 maxsteps
= atoi(args
[++argidx
].c_str());
993 if (args
[argidx
] == "-initsteps" && argidx
+1 < args
.size()) {
994 initsteps
= atoi(args
[++argidx
].c_str());
997 if (args
[argidx
] == "-ignore_div_by_zero") {
998 ignore_div_by_zero
= true;
1001 if (args
[argidx
] == "-enable_undef") {
1002 enable_undef
= true;
1005 if (args
[argidx
] == "-max_undef") {
1006 enable_undef
= true;
1010 if (args
[argidx
] == "-set-def-inputs") {
1011 enable_undef
= true;
1012 set_def_inputs
= true;
1015 if (args
[argidx
] == "-set" && argidx
+2 < args
.size()) {
1016 std::string lhs
= args
[++argidx
];
1017 std::string rhs
= args
[++argidx
];
1018 sets
.push_back(std::pair
<std::string
, std::string
>(lhs
, rhs
));
1021 if (args
[argidx
] == "-set-def" && argidx
+1 < args
.size()) {
1022 sets_def
.push_back(args
[++argidx
]);
1023 enable_undef
= true;
1026 if (args
[argidx
] == "-set-any-undef" && argidx
+1 < args
.size()) {
1027 sets_any_undef
.push_back(args
[++argidx
]);
1028 enable_undef
= true;
1031 if (args
[argidx
] == "-set-all-undef" && argidx
+1 < args
.size()) {
1032 sets_all_undef
.push_back(args
[++argidx
]);
1033 enable_undef
= true;
1036 if (args
[argidx
] == "-tempinduct") {
1040 if (args
[argidx
] == "-tempinduct-def") {
1042 tempinduct_def
= true;
1045 if (args
[argidx
] == "-prove" && argidx
+2 < args
.size()) {
1046 std::string lhs
= args
[++argidx
];
1047 std::string rhs
= args
[++argidx
];
1048 prove
.push_back(std::pair
<std::string
, std::string
>(lhs
, rhs
));
1051 if (args
[argidx
] == "-prove-x" && argidx
+2 < args
.size()) {
1052 std::string lhs
= args
[++argidx
];
1053 std::string rhs
= args
[++argidx
];
1054 prove_x
.push_back(std::pair
<std::string
, std::string
>(lhs
, rhs
));
1055 enable_undef
= true;
1058 if (args
[argidx
] == "-prove-asserts") {
1059 prove_asserts
= true;
1062 if (args
[argidx
] == "-seq" && argidx
+1 < args
.size()) {
1063 seq_len
= atoi(args
[++argidx
].c_str());
1066 if (args
[argidx
] == "-set-at" && argidx
+3 < args
.size()) {
1067 int timestep
= atoi(args
[++argidx
].c_str());
1068 std::string lhs
= args
[++argidx
];
1069 std::string rhs
= args
[++argidx
];
1070 sets_at
[timestep
].push_back(std::pair
<std::string
, std::string
>(lhs
, rhs
));
1073 if (args
[argidx
] == "-unset-at" && argidx
+2 < args
.size()) {
1074 int timestep
= atoi(args
[++argidx
].c_str());
1075 unsets_at
[timestep
].push_back(args
[++argidx
]);
1078 if (args
[argidx
] == "-set-def-at" && argidx
+2 < args
.size()) {
1079 int timestep
= atoi(args
[++argidx
].c_str());
1080 sets_def_at
[timestep
].push_back(args
[++argidx
]);
1081 enable_undef
= true;
1084 if (args
[argidx
] == "-set-any-undef-at" && argidx
+2 < args
.size()) {
1085 int timestep
= atoi(args
[++argidx
].c_str());
1086 sets_any_undef_at
[timestep
].push_back(args
[++argidx
]);
1087 enable_undef
= true;
1090 if (args
[argidx
] == "-set-all-undef-at" && argidx
+2 < args
.size()) {
1091 int timestep
= atoi(args
[++argidx
].c_str());
1092 sets_all_undef_at
[timestep
].push_back(args
[++argidx
]);
1093 enable_undef
= true;
1096 if (args
[argidx
] == "-set-init" && argidx
+2 < args
.size()) {
1097 std::string lhs
= args
[++argidx
];
1098 std::string rhs
= args
[++argidx
];
1099 sets_init
.push_back(std::pair
<std::string
, std::string
>(lhs
, rhs
));
1102 if (args
[argidx
] == "-set-init-undef") {
1103 set_init_undef
= true;
1104 enable_undef
= true;
1107 if (args
[argidx
] == "-set-init-def") {
1108 set_init_def
= true;
1111 if (args
[argidx
] == "-set-init-zero") {
1112 set_init_zero
= true;
1115 if (args
[argidx
] == "-show" && argidx
+1 < args
.size()) {
1116 shows
.push_back(args
[++argidx
]);
1119 if (args
[argidx
] == "-show-inputs") {
1123 if (args
[argidx
] == "-show-outputs") {
1124 show_outputs
= true;
1127 if (args
[argidx
] == "-ignore_unknown_cells") {
1128 ignore_unknown_cells
= true;
1131 if (args
[argidx
] == "-dump_vcd" && argidx
+1 < args
.size()) {
1132 vcd_file_name
= args
[++argidx
];
1135 if (args
[argidx
] == "-dump_cnf" && argidx
+1 < args
.size()) {
1136 cnf_file_name
= args
[++argidx
];
1141 extra_args(args
, argidx
, design
);
1143 RTLIL::Module
*module
= NULL
;
1144 for (auto &mod_it
: design
->modules
)
1145 if (design
->selected(mod_it
.second
)) {
1147 log_cmd_error("Only one module must be selected for the SAT pass! (selected: %s and %s)\n",
1148 RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(mod_it
.first
));
1149 module
= mod_it
.second
;
1152 log_cmd_error("Can't perform SAT on an empty selection!\n");
1154 if (!prove
.size() && !prove_x
.size() && !prove_asserts
&& tempinduct
)
1155 log_cmd_error("Got -tempinduct but nothing to prove!\n");
1157 if (set_init_undef
+ set_init_zero
+ set_init_def
> 1)
1158 log_cmd_error("The options -set-init-undef, -set-init-def, and -set-init-zero are exclusive!\n");
1160 if (set_def_inputs
) {
1161 for (auto &it
: module
->wires
)
1162 if (it
.second
->port_input
)
1163 sets_def
.push_back(it
.second
->name
);
1167 for (auto &it
: module
->wires
)
1168 if (it
.second
->port_input
)
1169 shows
.push_back(it
.second
->name
);
1173 for (auto &it
: module
->wires
)
1174 if (it
.second
->port_output
)
1175 shows
.push_back(it
.second
->name
);
1180 if (loopcount
> 0 || max_undef
)
1181 log_cmd_error("The options -max, -all, and -max_undef are not supported for temporal induction proofs!\n");
1183 SatHelper
basecase(design
, module
, enable_undef
);
1184 SatHelper
inductstep(design
, module
, enable_undef
);
1186 basecase
.sets
= sets
;
1187 basecase
.prove
= prove
;
1188 basecase
.prove_x
= prove_x
;
1189 basecase
.prove_asserts
= prove_asserts
;
1190 basecase
.sets_at
= sets_at
;
1191 basecase
.unsets_at
= unsets_at
;
1192 basecase
.shows
= shows
;
1193 basecase
.timeout
= timeout
;
1194 basecase
.sets_def
= sets_def
;
1195 basecase
.sets_any_undef
= sets_any_undef
;
1196 basecase
.sets_all_undef
= sets_all_undef
;
1197 basecase
.sets_def_at
= sets_def_at
;
1198 basecase
.sets_any_undef_at
= sets_any_undef_at
;
1199 basecase
.sets_all_undef_at
= sets_all_undef_at
;
1200 basecase
.sets_init
= sets_init
;
1201 basecase
.set_init_def
= set_init_def
;
1202 basecase
.set_init_undef
= set_init_undef
;
1203 basecase
.set_init_zero
= set_init_zero
;
1204 basecase
.satgen
.ignore_div_by_zero
= ignore_div_by_zero
;
1205 basecase
.ignore_unknown_cells
= ignore_unknown_cells
;
1207 for (int timestep
= 1; timestep
<= seq_len
; timestep
++)
1208 basecase
.setup(timestep
);
1209 basecase
.setup_init();
1211 inductstep
.sets
= sets
;
1212 inductstep
.prove
= prove
;
1213 inductstep
.prove_x
= prove_x
;
1214 inductstep
.prove_asserts
= prove_asserts
;
1215 inductstep
.shows
= shows
;
1216 inductstep
.timeout
= timeout
;
1217 inductstep
.sets_def
= sets_def
;
1218 inductstep
.sets_any_undef
= sets_any_undef
;
1219 inductstep
.sets_all_undef
= sets_all_undef
;
1220 inductstep
.satgen
.ignore_div_by_zero
= ignore_div_by_zero
;
1221 inductstep
.ignore_unknown_cells
= ignore_unknown_cells
;
1223 inductstep
.setup(1);
1224 inductstep
.ez
.assume(inductstep
.setup_proof(1));
1226 if (tempinduct_def
) {
1227 std::vector
<int> undef_state
= inductstep
.satgen
.importUndefSigSpec(inductstep
.satgen
.initial_state
.export_all(), 1);
1228 inductstep
.ez
.assume(inductstep
.ez
.NOT(inductstep
.ez
.expression(ezSAT::OpOr
, undef_state
)));
1231 for (int inductlen
= 1; inductlen
<= maxsteps
|| maxsteps
== 0; inductlen
++)
1233 log("\n** Trying induction with length %d **\n", inductlen
);
1235 // phase 1: proving base case
1237 basecase
.setup(seq_len
+ inductlen
);
1238 int property
= basecase
.setup_proof(seq_len
+ inductlen
);
1239 basecase
.generate_model();
1242 basecase
.force_unique_state(seq_len
+ 1, seq_len
+ inductlen
);
1244 log("\n[base case] Solving problem with %d variables and %d clauses..\n",
1245 basecase
.ez
.numCnfVariables(), basecase
.ez
.numCnfClauses());
1247 if (basecase
.solve(basecase
.ez
.NOT(property
))) {
1248 log("SAT temporal induction proof finished - model found for base case: FAIL!\n");
1249 print_proof_failed();
1250 basecase
.print_model();
1251 if(!vcd_file_name
.empty())
1252 basecase
.dump_model_to_vcd(vcd_file_name
);
1256 if (basecase
.gotTimeout
)
1259 log("Base case for induction length %d proven.\n", inductlen
);
1260 basecase
.ez
.assume(property
);
1262 // phase 2: proving induction step
1264 inductstep
.setup(inductlen
+ 1);
1265 property
= inductstep
.setup_proof(inductlen
+ 1);
1266 inductstep
.generate_model();
1269 inductstep
.force_unique_state(1, inductlen
+ 1);
1271 if (inductlen
< initsteps
)
1273 log("\n[induction step] Skipping problem with %d variables and %d clauses (below initsteps).\n",
1274 inductstep
.ez
.numCnfVariables(), inductstep
.ez
.numCnfClauses());
1275 inductstep
.ez
.assume(property
);
1279 if (!cnf_file_name
.empty())
1281 FILE *f
= fopen(cnf_file_name
.c_str(), "w");
1283 log_cmd_error("Can't open output file `%s' for writing: %s\n", cnf_file_name
.c_str(), strerror(errno
));
1285 log("Dumping CNF to file `%s'.\n", cnf_file_name
.c_str());
1286 cnf_file_name
.clear();
1288 inductstep
.ez
.printDIMACS(f
, false);
1292 log("\n[induction step] Solving problem with %d variables and %d clauses..\n",
1293 inductstep
.ez
.numCnfVariables(), inductstep
.ez
.numCnfClauses());
1295 if (!inductstep
.solve(inductstep
.ez
.NOT(property
))) {
1296 if (inductstep
.gotTimeout
)
1298 log("Induction step proven: SUCCESS!\n");
1303 log("Induction step failed. Incrementing induction length.\n");
1304 inductstep
.ez
.assume(property
);
1305 inductstep
.print_model();
1309 log("\nReached maximum number of time steps -> proof failed.\n");
1310 print_proof_failed();
1315 log_error("Called with -verify and proof did fail!\n");
1322 log_error("Called with -falsify and proof did succeed!\n");
1328 log_cmd_error("The options -maxsteps is only supported for temporal induction proofs!\n");
1330 SatHelper
sathelper(design
, module
, enable_undef
);
1332 sathelper
.sets
= sets
;
1333 sathelper
.prove
= prove
;
1334 sathelper
.prove_x
= prove_x
;
1335 sathelper
.prove_asserts
= prove_asserts
;
1336 sathelper
.sets_at
= sets_at
;
1337 sathelper
.unsets_at
= unsets_at
;
1338 sathelper
.shows
= shows
;
1339 sathelper
.timeout
= timeout
;
1340 sathelper
.sets_def
= sets_def
;
1341 sathelper
.sets_any_undef
= sets_any_undef
;
1342 sathelper
.sets_all_undef
= sets_all_undef
;
1343 sathelper
.sets_def_at
= sets_def_at
;
1344 sathelper
.sets_any_undef_at
= sets_any_undef_at
;
1345 sathelper
.sets_all_undef_at
= sets_all_undef_at
;
1346 sathelper
.sets_init
= sets_init
;
1347 sathelper
.set_init_def
= set_init_def
;
1348 sathelper
.set_init_undef
= set_init_undef
;
1349 sathelper
.set_init_zero
= set_init_zero
;
1350 sathelper
.satgen
.ignore_div_by_zero
= ignore_div_by_zero
;
1351 sathelper
.ignore_unknown_cells
= ignore_unknown_cells
;
1355 if (sathelper
.prove
.size() || sathelper
.prove_x
.size() || sathelper
.prove_asserts
)
1356 sathelper
.ez
.assume(sathelper
.ez
.NOT(sathelper
.setup_proof()));
1358 std::vector
<int> prove_bits
;
1359 for (int timestep
= 1; timestep
<= seq_len
; timestep
++) {
1360 sathelper
.setup(timestep
);
1361 if (sathelper
.prove
.size() || sathelper
.prove_x
.size() || sathelper
.prove_asserts
)
1362 prove_bits
.push_back(sathelper
.setup_proof(timestep
));
1364 if (sathelper
.prove
.size() || sathelper
.prove_x
.size() || sathelper
.prove_asserts
)
1365 sathelper
.ez
.assume(sathelper
.ez
.NOT(sathelper
.ez
.expression(ezSAT::OpAnd
, prove_bits
)));
1366 sathelper
.setup_init();
1368 sathelper
.generate_model();
1370 if (!cnf_file_name
.empty())
1372 FILE *f
= fopen(cnf_file_name
.c_str(), "w");
1374 log_cmd_error("Can't open output file `%s' for writing: %s\n", cnf_file_name
.c_str(), strerror(errno
));
1376 log("Dumping CNF to file `%s'.\n", cnf_file_name
.c_str());
1377 cnf_file_name
.clear();
1379 sathelper
.ez
.printDIMACS(f
, false);
1383 int rerun_counter
= 0;
1386 log("\nSolving problem with %d variables and %d clauses..\n",
1387 sathelper
.ez
.numCnfVariables(), sathelper
.ez
.numCnfClauses());
1389 if (sathelper
.solve())
1392 log("SAT model found. maximizing number of undefs.\n");
1393 sathelper
.maximize_undefs();
1396 if (!prove
.size() && !prove_x
.size() && !prove_asserts
) {
1397 log("SAT solving finished - model found:\n");
1399 log("SAT proof finished - model found: FAIL!\n");
1400 print_proof_failed();
1403 sathelper
.print_model();
1405 if(!vcd_file_name
.empty())
1406 sathelper
.dump_model_to_vcd(vcd_file_name
);
1408 if (loopcount
!= 0) {
1409 loopcount
--, rerun_counter
++;
1410 sathelper
.invalidate_model(max_undef
);
1414 if (!prove
.size() && !prove_x
.size() && !prove_asserts
) {
1417 log_error("Called with -falsify and found a model!\n");
1422 log_error("Called with -verify and proof did fail!\n");
1428 if (sathelper
.gotTimeout
)
1431 log("SAT solving finished - no more models found (after %d distinct solutions).\n", rerun_counter
);
1432 else if (!prove
.size() && !prove_x
.size() && !prove_asserts
) {
1433 log("SAT solving finished - no model found.\n");
1436 log_error("Called with -verify and found no model!\n");
1439 log("SAT proof finished - no model found: SUCCESS!\n");
1443 log_error("Called with -falsify and proof did succeed!\n");
1448 if (!prove
.size() && !prove_x
.size() && !prove_asserts
) {
1449 if (falsify
&& rerun_counter
) {
1451 log_error("Called with -falsify and found a model!\n");
1454 if (verify
&& rerun_counter
) {
1456 log_error("Called with -verify and proof did fail!\n");
1463 log("Interrupted SAT solver: TIMEOUT!\n");
1465 if (fail_on_timeout
)
1466 log_error("Called with -verify and proof did time out!\n");