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.
23 #include "kernel/rtlil.h"
24 #include "kernel/sigtools.h"
25 #include "kernel/celltypes.h"
27 #ifdef YOSYS_ENABLE_MINISAT
28 # include "libs/ezsat/ezminisat.h"
29 typedef ezMiniSAT ezDefaultSAT
;
31 # include "libs/ezsat/ezsat.h"
32 typedef ezSAT ezDefaultSAT
;
40 SigPool initial_state
;
41 bool ignore_div_by_zero
;
44 SatGen(ezSAT
*ez
, SigMap
*sigmap
, std::string prefix
= std::string()) :
45 ez(ez
), sigmap(sigmap
), prefix(prefix
), ignore_div_by_zero(false), model_undef(false)
49 void setContext(SigMap
*sigmap
, std::string prefix
= std::string())
51 this->sigmap
= sigmap
;
52 this->prefix
= prefix
;
55 std::vector
<int> importSigSpecWorker(RTLIL::SigSpec
&sig
, std::string
&pf
, bool undef_mode
, bool dup_undef
)
57 log_assert(!undef_mode
|| model_undef
);
62 vec
.reserve(sig
.chunks
.size());
64 for (auto &c
: sig
.chunks
)
66 RTLIL::State bit
= c
.data
.bits
.at(0);
67 if (model_undef
&& dup_undef
&& bit
== RTLIL::State::Sx
)
68 vec
.push_back(ez
->literal());
70 vec
.push_back(bit
== (undef_mode
? RTLIL::State::Sx
: RTLIL::State::S1
) ? ez
->TRUE
: ez
->FALSE
);
72 std::string name
= pf
+ stringf(c
.wire
->width
== 1 ? "%s" : "%s [%d]", RTLIL::id2cstr(c
.wire
->name
), c
.offset
);
73 vec
.push_back(ez
->literal(name
));
78 std::vector
<int> importSigSpec(RTLIL::SigSpec sig
, int timestep
= -1)
80 log_assert(timestep
!= 0);
81 std::string pf
= prefix
+ (timestep
== -1 ? "" : stringf("@%d:", timestep
));
82 return importSigSpecWorker(sig
, pf
, false, false);
85 std::vector
<int> importDefSigSpec(RTLIL::SigSpec sig
, int timestep
= -1)
87 log_assert(timestep
!= 0);
88 std::string pf
= prefix
+ (timestep
== -1 ? "" : stringf("@%d:", timestep
));
89 return importSigSpecWorker(sig
, pf
, false, true);
92 std::vector
<int> importUndefSigSpec(RTLIL::SigSpec sig
, int timestep
= -1)
94 log_assert(timestep
!= 0);
95 std::string pf
= "undef:" + prefix
+ (timestep
== -1 ? "" : stringf("@%d:", timestep
));
96 return importSigSpecWorker(sig
, pf
, true, false);
99 int signals_eq(RTLIL::SigSpec lhs
, RTLIL::SigSpec rhs
, int timestep_lhs
= -1, int timestep_rhs
= -1)
101 if (timestep_rhs
< 0)
102 timestep_rhs
= timestep_lhs
;
104 assert(lhs
.width
== rhs
.width
);
106 std::vector
<int> vec_lhs
= importSigSpec(lhs
, timestep_lhs
);
107 std::vector
<int> vec_rhs
= importSigSpec(rhs
, timestep_rhs
);
110 return ez
->vec_eq(vec_lhs
, vec_rhs
);
112 std::vector
<int> undef_lhs
= importUndefSigSpec(lhs
, timestep_lhs
);
113 std::vector
<int> undef_rhs
= importUndefSigSpec(rhs
, timestep_rhs
);
115 std::vector
<int> eq_bits
;
116 for (int i
= 0; i
< lhs
.width
; i
++)
117 eq_bits
.push_back(ez
->AND(ez
->IFF(undef_lhs
.at(i
), undef_rhs
.at(i
)),
118 ez
->IFF(ez
->OR(vec_lhs
.at(i
), undef_lhs
.at(i
)), ez
->OR(vec_rhs
.at(i
), undef_rhs
.at(i
)))));
119 return ez
->expression(ezSAT::OpAnd
, eq_bits
);
122 void extendSignalWidth(std::vector
<int> &vec_a
, std::vector
<int> &vec_b
, RTLIL::Cell
*cell
, size_t y_width
= 0, bool forced_signed
= false)
124 bool is_signed
= forced_signed
;
125 if (!forced_signed
&& cell
->parameters
.count("\\A_SIGNED") > 0 && cell
->parameters
.count("\\B_SIGNED") > 0)
126 is_signed
= cell
->parameters
["\\A_SIGNED"].as_bool() && cell
->parameters
["\\B_SIGNED"].as_bool();
127 while (vec_a
.size() < vec_b
.size() || vec_a
.size() < y_width
)
128 vec_a
.push_back(is_signed
&& vec_a
.size() > 0 ? vec_a
.back() : ez
->FALSE
);
129 while (vec_b
.size() < vec_a
.size() || vec_b
.size() < y_width
)
130 vec_b
.push_back(is_signed
&& vec_b
.size() > 0 ? vec_b
.back() : ez
->FALSE
);
133 void extendSignalWidth(std::vector
<int> &vec_a
, std::vector
<int> &vec_b
, std::vector
<int> &vec_y
, RTLIL::Cell
*cell
, bool forced_signed
= false)
135 extendSignalWidth(vec_a
, vec_b
, cell
, vec_y
.size(), forced_signed
);
136 while (vec_y
.size() < vec_a
.size())
137 vec_y
.push_back(ez
->literal());
140 void extendSignalWidthUnary(std::vector
<int> &vec_a
, std::vector
<int> &vec_y
, RTLIL::Cell
*cell
, bool forced_signed
= false)
142 bool is_signed
= forced_signed
|| (cell
->parameters
.count("\\A_SIGNED") > 0 && cell
->parameters
["\\A_SIGNED"].as_bool());
143 while (vec_a
.size() < vec_y
.size())
144 vec_a
.push_back(is_signed
&& vec_a
.size() > 0 ? vec_a
.back() : ez
->FALSE
);
145 while (vec_y
.size() < vec_a
.size())
146 vec_y
.push_back(ez
->literal());
149 void undefGating(std::vector
<int> &vec_y
, std::vector
<int> &vec_yy
, std::vector
<int> &vec_undef
)
152 ez
->assume(ez
->expression(ezSAT::OpAnd
, ez
->vec_or(vec_undef
, ez
->vec_iff(vec_y
, vec_yy
))));
155 bool importCell(RTLIL::Cell
*cell
, int timestep
= -1)
157 bool arith_undef_handled
= false;
158 bool is_arith_compare
= cell
->type
== "$lt" || cell
->type
== "$le" || cell
->type
== "$ge" || cell
->type
== "$gt";
160 if (model_undef
&& (cell
->type
== "$add" || cell
->type
== "$sub" || cell
->type
== "$mul" || cell
->type
== "$div" || cell
->type
== "$mod" || is_arith_compare
))
162 std::vector
<int> undef_a
= importUndefSigSpec(cell
->connections
.at("\\A"), timestep
);
163 std::vector
<int> undef_b
= importUndefSigSpec(cell
->connections
.at("\\B"), timestep
);
164 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
165 if (is_arith_compare
)
166 extendSignalWidth(undef_a
, undef_b
, cell
, true);
168 extendSignalWidth(undef_a
, undef_b
, undef_y
, cell
, true);
170 int undef_any_a
= ez
->expression(ezSAT::OpOr
, undef_a
);
171 int undef_any_b
= ez
->expression(ezSAT::OpOr
, undef_b
);
172 int undef_y_bit
= ez
->OR(undef_any_a
, undef_any_b
);
174 if (cell
->type
== "$div" || cell
->type
== "$mod") {
175 std::vector
<int> b
= importSigSpec(cell
->connections
.at("\\B"), timestep
);
176 undef_y_bit
= ez
->OR(undef_y_bit
, ez
->NOT(ez
->expression(ezSAT::OpOr
, b
)));
179 if (is_arith_compare
) {
180 for (size_t i
= 1; i
< undef_y
.size(); i
++)
181 ez
->SET(ez
->FALSE
, undef_y
.at(i
));
182 ez
->SET(undef_y_bit
, undef_y
.at(0));
184 std::vector
<int> undef_y_bits(undef_y
.size(), undef_y_bit
);
185 ez
->assume(ez
->vec_eq(undef_y_bits
, undef_y
));
188 arith_undef_handled
= true;
191 if (cell
->type
== "$_AND_" || cell
->type
== "$_OR_" || cell
->type
== "$_XOR_" ||
192 cell
->type
== "$and" || cell
->type
== "$or" || cell
->type
== "$xor" || cell
->type
== "$xnor" ||
193 cell
->type
== "$add" || cell
->type
== "$sub")
195 std::vector
<int> a
= importDefSigSpec(cell
->connections
.at("\\A"), timestep
);
196 std::vector
<int> b
= importDefSigSpec(cell
->connections
.at("\\B"), timestep
);
197 std::vector
<int> y
= importDefSigSpec(cell
->connections
.at("\\Y"), timestep
);
198 extendSignalWidth(a
, b
, y
, cell
);
200 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
202 if (cell
->type
== "$and" || cell
->type
== "$_AND_")
203 ez
->assume(ez
->vec_eq(ez
->vec_and(a
, b
), yy
));
204 if (cell
->type
== "$or" || cell
->type
== "$_OR_")
205 ez
->assume(ez
->vec_eq(ez
->vec_or(a
, b
), yy
));
206 if (cell
->type
== "$xor" || cell
->type
== "$_XOR_")
207 ez
->assume(ez
->vec_eq(ez
->vec_xor(a
, b
), yy
));
208 if (cell
->type
== "$xnor")
209 ez
->assume(ez
->vec_eq(ez
->vec_not(ez
->vec_xor(a
, b
)), yy
));
210 if (cell
->type
== "$add")
211 ez
->assume(ez
->vec_eq(ez
->vec_add(a
, b
), yy
));
212 if (cell
->type
== "$sub")
213 ez
->assume(ez
->vec_eq(ez
->vec_sub(a
, b
), yy
));
215 if (model_undef
&& !arith_undef_handled
)
217 std::vector
<int> undef_a
= importUndefSigSpec(cell
->connections
.at("\\A"), timestep
);
218 std::vector
<int> undef_b
= importUndefSigSpec(cell
->connections
.at("\\B"), timestep
);
219 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
220 extendSignalWidth(undef_a
, undef_b
, undef_y
, cell
, false);
222 if (cell
->type
== "$and" || cell
->type
== "$_AND_") {
223 std::vector
<int> a0
= ez
->vec_and(ez
->vec_not(a
), ez
->vec_not(undef_a
));
224 std::vector
<int> b0
= ez
->vec_and(ez
->vec_not(b
), ez
->vec_not(undef_b
));
225 std::vector
<int> yX
= ez
->vec_and(ez
->vec_or(undef_a
, undef_b
), ez
->vec_not(ez
->vec_or(a0
, b0
)));
226 ez
->assume(ez
->vec_eq(yX
, undef_y
));
228 else if (cell
->type
== "$or" || cell
->type
== "$_OR_") {
229 std::vector
<int> a1
= ez
->vec_and(a
, ez
->vec_not(undef_a
));
230 std::vector
<int> b1
= ez
->vec_and(b
, ez
->vec_not(undef_b
));
231 std::vector
<int> yX
= ez
->vec_and(ez
->vec_or(undef_a
, undef_b
), ez
->vec_not(ez
->vec_or(a1
, b1
)));
232 ez
->assume(ez
->vec_eq(yX
, undef_y
));
234 else if (cell
->type
== "$xor" || cell
->type
== "$_XOR_" || cell
->type
== "$xnor") {
235 std::vector
<int> yX
= ez
->vec_or(undef_a
, undef_b
);
236 ez
->assume(ez
->vec_eq(yX
, undef_y
));
241 undefGating(y
, yy
, undef_y
);
243 else if (model_undef
)
245 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
246 undefGating(y
, yy
, undef_y
);
251 if (cell
->type
== "$_INV_" || cell
->type
== "$not")
253 std::vector
<int> a
= importDefSigSpec(cell
->connections
.at("\\A"), timestep
);
254 std::vector
<int> y
= importDefSigSpec(cell
->connections
.at("\\Y"), timestep
);
255 extendSignalWidthUnary(a
, y
, cell
);
257 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
258 ez
->assume(ez
->vec_eq(ez
->vec_not(a
), yy
));
261 std::vector
<int> undef_a
= importUndefSigSpec(cell
->connections
.at("\\A"), timestep
);
262 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
263 extendSignalWidthUnary(undef_a
, undef_y
, cell
, true);
264 ez
->assume(ez
->vec_eq(undef_a
, undef_y
));
265 undefGating(y
, yy
, undef_y
);
270 if (cell
->type
== "$_MUX_" || cell
->type
== "$mux")
272 std::vector
<int> a
= importDefSigSpec(cell
->connections
.at("\\A"), timestep
);
273 std::vector
<int> b
= importDefSigSpec(cell
->connections
.at("\\B"), timestep
);
274 std::vector
<int> s
= importDefSigSpec(cell
->connections
.at("\\S"), timestep
);
275 std::vector
<int> y
= importDefSigSpec(cell
->connections
.at("\\Y"), timestep
);
277 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
278 ez
->assume(ez
->vec_eq(ez
->vec_ite(s
.at(0), b
, a
), yy
));
282 std::vector
<int> undef_a
= importUndefSigSpec(cell
->connections
.at("\\A"), timestep
);
283 std::vector
<int> undef_b
= importUndefSigSpec(cell
->connections
.at("\\B"), timestep
);
284 std::vector
<int> undef_s
= importUndefSigSpec(cell
->connections
.at("\\S"), timestep
);
285 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
287 std::vector
<int> unequal_ab
= ez
->vec_not(ez
->vec_iff(a
, b
));
288 std::vector
<int> undef_ab
= ez
->vec_or(unequal_ab
, ez
->vec_or(undef_a
, undef_b
));
289 std::vector
<int> yX
= ez
->vec_ite(undef_s
.at(0), undef_ab
, ez
->vec_ite(s
.at(0), undef_b
, undef_a
));
290 ez
->assume(ez
->vec_eq(yX
, undef_y
));
291 undefGating(y
, yy
, undef_y
);
296 if (cell
->type
== "$pmux" || cell
->type
== "$safe_pmux")
298 std::vector
<int> a
= importDefSigSpec(cell
->connections
.at("\\A"), timestep
);
299 std::vector
<int> b
= importDefSigSpec(cell
->connections
.at("\\B"), timestep
);
300 std::vector
<int> s
= importDefSigSpec(cell
->connections
.at("\\S"), timestep
);
301 std::vector
<int> y
= importDefSigSpec(cell
->connections
.at("\\Y"), timestep
);
303 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
305 std::vector
<int> tmp
= a
;
306 for (size_t i
= 0; i
< s
.size(); i
++) {
307 std::vector
<int> part_of_b(b
.begin()+i
*a
.size(), b
.begin()+(i
+1)*a
.size());
308 tmp
= ez
->vec_ite(s
.at(i
), part_of_b
, tmp
);
310 if (cell
->type
== "$safe_pmux")
311 tmp
= ez
->vec_ite(ez
->onehot(s
, true), tmp
, a
);
312 ez
->assume(ez
->vec_eq(tmp
, yy
));
316 std::vector
<int> undef_a
= importUndefSigSpec(cell
->connections
.at("\\A"), timestep
);
317 std::vector
<int> undef_b
= importUndefSigSpec(cell
->connections
.at("\\B"), timestep
);
318 std::vector
<int> undef_s
= importUndefSigSpec(cell
->connections
.at("\\S"), timestep
);
319 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
322 for (size_t i
= 0; i
< s
.size(); i
++) {
323 std::vector
<int> part_of_undef_b(undef_b
.begin()+i
*a
.size(), undef_b
.begin()+(i
+1)*a
.size());
324 tmp
= ez
->vec_ite(s
.at(i
), part_of_undef_b
, tmp
);
326 tmp
= ez
->vec_ite(ez
->onehot(s
, true), tmp
, cell
->type
== "$safe_pmux" ? a
: std::vector
<int>(tmp
.size(), ez
->TRUE
));
327 tmp
= ez
->vec_ite(ez
->expression(ezSAT::OpOr
, undef_s
), std::vector
<int>(tmp
.size(), ez
->TRUE
), tmp
);
328 ez
->assume(ez
->vec_eq(tmp
, undef_y
));
329 undefGating(y
, yy
, undef_y
);
334 if (cell
->type
== "$pos" || cell
->type
== "$neg")
336 std::vector
<int> a
= importDefSigSpec(cell
->connections
.at("\\A"), timestep
);
337 std::vector
<int> y
= importDefSigSpec(cell
->connections
.at("\\Y"), timestep
);
338 extendSignalWidthUnary(a
, y
, cell
);
340 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
342 if (cell
->type
== "$pos") {
343 ez
->assume(ez
->vec_eq(a
, yy
));
345 std::vector
<int> zero(a
.size(), ez
->FALSE
);
346 ez
->assume(ez
->vec_eq(ez
->vec_sub(zero
, a
), yy
));
351 std::vector
<int> undef_a
= importUndefSigSpec(cell
->connections
.at("\\A"), timestep
);
352 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
353 extendSignalWidthUnary(undef_a
, undef_y
, cell
, true);
355 if (cell
->type
== "$pos") {
356 ez
->assume(ez
->vec_eq(undef_a
, undef_y
));
358 int undef_any_a
= ez
->expression(ezSAT::OpOr
, undef_a
);
359 std::vector
<int> undef_y_bits(undef_y
.size(), undef_any_a
);
360 ez
->assume(ez
->vec_eq(undef_y_bits
, undef_y
));
363 undefGating(y
, yy
, undef_y
);
368 if (cell
->type
== "$reduce_and" || cell
->type
== "$reduce_or" || cell
->type
== "$reduce_xor" ||
369 cell
->type
== "$reduce_xnor" || cell
->type
== "$reduce_bool" || cell
->type
== "$logic_not")
371 std::vector
<int> a
= importDefSigSpec(cell
->connections
.at("\\A"), timestep
);
372 std::vector
<int> y
= importDefSigSpec(cell
->connections
.at("\\Y"), timestep
);
374 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
376 if (cell
->type
== "$reduce_and")
377 ez
->SET(ez
->expression(ez
->OpAnd
, a
), yy
.at(0));
378 if (cell
->type
== "$reduce_or" || cell
->type
== "$reduce_bool")
379 ez
->SET(ez
->expression(ez
->OpOr
, a
), yy
.at(0));
380 if (cell
->type
== "$reduce_xor")
381 ez
->SET(ez
->expression(ez
->OpXor
, a
), yy
.at(0));
382 if (cell
->type
== "$reduce_xnor")
383 ez
->SET(ez
->NOT(ez
->expression(ez
->OpXor
, a
)), yy
.at(0));
384 if (cell
->type
== "$logic_not")
385 ez
->SET(ez
->NOT(ez
->expression(ez
->OpOr
, a
)), yy
.at(0));
386 for (size_t i
= 1; i
< y
.size(); i
++)
387 ez
->SET(ez
->FALSE
, yy
.at(i
));
391 std::vector
<int> undef_a
= importUndefSigSpec(cell
->connections
.at("\\A"), timestep
);
392 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
393 int aX
= ez
->expression(ezSAT::OpOr
, undef_a
);
395 if (cell
->type
== "$reduce_and") {
396 int a0
= ez
->expression(ezSAT::OpOr
, ez
->vec_and(ez
->vec_not(a
), ez
->vec_not(undef_a
)));
397 ez
->assume(ez
->IFF(ez
->AND(ez
->NOT(a0
), aX
), undef_y
.at(0)));
399 else if (cell
->type
== "$reduce_or" || cell
->type
== "$reduce_bool" || cell
->type
== "$logic_not") {
400 int a1
= ez
->expression(ezSAT::OpOr
, ez
->vec_and(a
, ez
->vec_not(undef_a
)));
401 ez
->assume(ez
->IFF(ez
->AND(ez
->NOT(a1
), aX
), undef_y
.at(0)));
403 else if (cell
->type
== "$reduce_xor" || cell
->type
== "$reduce_xnor") {
404 ez
->assume(ez
->IFF(aX
, undef_y
.at(0)));
408 for (size_t i
= 1; i
< undef_y
.size(); i
++)
409 ez
->SET(ez
->FALSE
, undef_y
.at(i
));
411 undefGating(y
, yy
, undef_y
);
416 if (cell
->type
== "$logic_and" || cell
->type
== "$logic_or")
418 std::vector
<int> vec_a
= importDefSigSpec(cell
->connections
.at("\\A"), timestep
);
419 std::vector
<int> vec_b
= importDefSigSpec(cell
->connections
.at("\\B"), timestep
);
421 int a
= ez
->expression(ez
->OpOr
, vec_a
);
422 int b
= ez
->expression(ez
->OpOr
, vec_b
);
423 std::vector
<int> y
= importDefSigSpec(cell
->connections
.at("\\Y"), timestep
);
425 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
427 if (cell
->type
== "$logic_and")
428 ez
->SET(ez
->expression(ez
->OpAnd
, a
, b
), yy
.at(0));
430 ez
->SET(ez
->expression(ez
->OpOr
, a
, b
), yy
.at(0));
431 for (size_t i
= 1; i
< y
.size(); i
++)
432 ez
->SET(ez
->FALSE
, yy
.at(i
));
436 std::vector
<int> undef_a
= importUndefSigSpec(cell
->connections
.at("\\A"), timestep
);
437 std::vector
<int> undef_b
= importUndefSigSpec(cell
->connections
.at("\\B"), timestep
);
438 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
440 int a0
= ez
->NOT(ez
->OR(ez
->expression(ezSAT::OpOr
, vec_a
), ez
->expression(ezSAT::OpOr
, undef_a
)));
441 int b0
= ez
->NOT(ez
->OR(ez
->expression(ezSAT::OpOr
, vec_b
), ez
->expression(ezSAT::OpOr
, undef_b
)));
442 int a1
= ez
->expression(ezSAT::OpOr
, ez
->vec_and(vec_a
, ez
->vec_not(undef_a
)));
443 int b1
= ez
->expression(ezSAT::OpOr
, ez
->vec_and(vec_b
, ez
->vec_not(undef_b
)));
444 int aX
= ez
->expression(ezSAT::OpOr
, undef_a
);
445 int bX
= ez
->expression(ezSAT::OpOr
, undef_b
);
447 if (cell
->type
== "$logic_and")
448 ez
->SET(ez
->AND(ez
->OR(aX
, bX
), ez
->NOT(ez
->AND(a1
, b1
)), ez
->NOT(a0
), ez
->NOT(b0
)), undef_y
.at(0));
449 else if (cell
->type
== "$logic_or")
450 ez
->SET(ez
->AND(ez
->OR(aX
, bX
), ez
->NOT(ez
->AND(a0
, b0
)), ez
->NOT(a1
), ez
->NOT(b1
)), undef_y
.at(0));
454 for (size_t i
= 1; i
< undef_y
.size(); i
++)
455 ez
->SET(ez
->FALSE
, undef_y
.at(i
));
457 undefGating(y
, yy
, undef_y
);
462 if (cell
->type
== "$lt" || cell
->type
== "$le" || cell
->type
== "$eq" || cell
->type
== "$ne" || cell
->type
== "$eqx" || cell
->type
== "$nex" || cell
->type
== "$ge" || cell
->type
== "$gt")
464 bool is_signed
= cell
->parameters
["\\A_SIGNED"].as_bool() && cell
->parameters
["\\B_SIGNED"].as_bool();
465 std::vector
<int> a
= importDefSigSpec(cell
->connections
.at("\\A"), timestep
);
466 std::vector
<int> b
= importDefSigSpec(cell
->connections
.at("\\B"), timestep
);
467 std::vector
<int> y
= importDefSigSpec(cell
->connections
.at("\\Y"), timestep
);
468 extendSignalWidth(a
, b
, cell
);
470 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
472 if (model_undef
&& (cell
->type
== "$eqx" || cell
->type
== "$nex")) {
473 std::vector
<int> undef_a
= importUndefSigSpec(cell
->connections
.at("\\A"), timestep
);
474 std::vector
<int> undef_b
= importUndefSigSpec(cell
->connections
.at("\\B"), timestep
);
475 extendSignalWidth(undef_a
, undef_b
, cell
, true);
476 a
= ez
->vec_or(a
, undef_a
);
477 b
= ez
->vec_or(b
, undef_b
);
480 if (cell
->type
== "$lt")
481 ez
->SET(is_signed
? ez
->vec_lt_signed(a
, b
) : ez
->vec_lt_unsigned(a
, b
), yy
.at(0));
482 if (cell
->type
== "$le")
483 ez
->SET(is_signed
? ez
->vec_le_signed(a
, b
) : ez
->vec_le_unsigned(a
, b
), yy
.at(0));
484 if (cell
->type
== "$eq" || cell
->type
== "$eqx")
485 ez
->SET(ez
->vec_eq(a
, b
), yy
.at(0));
486 if (cell
->type
== "$ne" || cell
->type
== "$nex")
487 ez
->SET(ez
->vec_ne(a
, b
), yy
.at(0));
488 if (cell
->type
== "$ge")
489 ez
->SET(is_signed
? ez
->vec_ge_signed(a
, b
) : ez
->vec_ge_unsigned(a
, b
), yy
.at(0));
490 if (cell
->type
== "$gt")
491 ez
->SET(is_signed
? ez
->vec_gt_signed(a
, b
) : ez
->vec_gt_unsigned(a
, b
), yy
.at(0));
492 for (size_t i
= 1; i
< y
.size(); i
++)
493 ez
->SET(ez
->FALSE
, yy
.at(i
));
495 if (model_undef
&& (cell
->type
== "$eqx" || cell
->type
== "$nex"))
497 std::vector
<int> undef_a
= importUndefSigSpec(cell
->connections
.at("\\A"), timestep
);
498 std::vector
<int> undef_b
= importUndefSigSpec(cell
->connections
.at("\\B"), timestep
);
499 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
500 extendSignalWidth(undef_a
, undef_b
, cell
, true);
502 if (cell
->type
== "$eqx")
503 yy
.at(0) = ez
->AND(yy
.at(0), ez
->vec_eq(undef_a
, undef_b
));
505 yy
.at(0) = ez
->OR(yy
.at(0), ez
->vec_ne(undef_a
, undef_b
));
507 for (size_t i
= 0; i
< y
.size(); i
++)
508 ez
->SET(ez
->FALSE
, undef_y
.at(i
));
510 ez
->assume(ez
->vec_eq(y
, yy
));
512 else if (model_undef
&& (cell
->type
== "$eq" || cell
->type
== "$ne"))
514 std::vector
<int> undef_a
= importUndefSigSpec(cell
->connections
.at("\\A"), timestep
);
515 std::vector
<int> undef_b
= importUndefSigSpec(cell
->connections
.at("\\B"), timestep
);
516 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
517 extendSignalWidth(undef_a
, undef_b
, cell
, true);
519 int undef_any_a
= ez
->expression(ezSAT::OpOr
, undef_a
);
520 int undef_any_b
= ez
->expression(ezSAT::OpOr
, undef_b
);
521 int undef_any
= ez
->OR(undef_any_a
, undef_any_b
);
523 std::vector
<int> masked_a_bits
= ez
->vec_or(a
, ez
->vec_or(undef_a
, undef_b
));
524 std::vector
<int> masked_b_bits
= ez
->vec_or(b
, ez
->vec_or(undef_a
, undef_b
));
526 int masked_ne
= ez
->vec_ne(masked_a_bits
, masked_b_bits
);
527 int undef_y_bit
= ez
->AND(undef_any
, ez
->NOT(masked_ne
));
529 for (size_t i
= 1; i
< undef_y
.size(); i
++)
530 ez
->SET(ez
->FALSE
, undef_y
.at(i
));
531 ez
->SET(undef_y_bit
, undef_y
.at(0));
533 undefGating(y
, yy
, undef_y
);
538 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
539 undefGating(y
, yy
, undef_y
);
541 log_assert(!model_undef
|| arith_undef_handled
);
546 if (cell
->type
== "$shl" || cell
->type
== "$shr" || cell
->type
== "$sshl" || cell
->type
== "$sshr")
548 std::vector
<int> a
= importDefSigSpec(cell
->connections
.at("\\A"), timestep
);
549 std::vector
<int> b
= importDefSigSpec(cell
->connections
.at("\\B"), timestep
);
550 std::vector
<int> y
= importDefSigSpec(cell
->connections
.at("\\Y"), timestep
);
552 char shift_left
= cell
->type
== "$shl" || cell
->type
== "$sshl";
553 bool sign_extend
= cell
->type
== "$sshr" && cell
->parameters
["\\A_SIGNED"].as_bool();
555 while (y
.size() < a
.size())
556 y
.push_back(ez
->literal());
557 while (y
.size() > a
.size())
558 a
.push_back(cell
->parameters
["\\A_SIGNED"].as_bool() ? a
.back() : ez
->FALSE
);
560 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
562 std::vector
<int> tmp
= a
;
563 for (size_t i
= 0; i
< b
.size(); i
++)
565 std::vector
<int> tmp_shifted(tmp
.size());
566 for (size_t j
= 0; j
< tmp
.size(); j
++) {
567 int idx
= j
+ (1 << (i
> 30 ? 30 : i
)) * (shift_left
? -1 : +1);
568 tmp_shifted
.at(j
) = (0 <= idx
&& idx
< int(tmp
.size())) ? tmp
.at(idx
) : sign_extend
? tmp
.back() : ez
->FALSE
;
570 tmp
= ez
->vec_ite(b
.at(i
), tmp_shifted
, tmp
);
572 ez
->assume(ez
->vec_eq(tmp
, yy
));
576 std::vector
<int> undef_a
= importUndefSigSpec(cell
->connections
.at("\\A"), timestep
);
577 std::vector
<int> undef_b
= importUndefSigSpec(cell
->connections
.at("\\B"), timestep
);
578 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
580 while (undef_y
.size() < undef_a
.size())
581 undef_y
.push_back(ez
->literal());
582 while (undef_y
.size() > undef_a
.size())
583 undef_a
.push_back(undef_a
.back());
586 for (size_t i
= 0; i
< b
.size(); i
++)
588 std::vector
<int> tmp_shifted(tmp
.size());
589 for (size_t j
= 0; j
< tmp
.size(); j
++) {
590 int idx
= j
+ (1 << (i
> 30 ? 30 : i
)) * (shift_left
? -1 : +1);
591 tmp_shifted
.at(j
) = (0 <= idx
&& idx
< int(tmp
.size())) ? tmp
.at(idx
) : sign_extend
? tmp
.back() : ez
->FALSE
;
593 tmp
= ez
->vec_ite(b
.at(i
), tmp_shifted
, tmp
);
596 int undef_any_b
= ez
->expression(ezSAT::OpOr
, undef_b
);
597 std::vector
<int> undef_all_y_bits(undef_y
.size(), undef_any_b
);
598 ez
->assume(ez
->vec_eq(ez
->vec_or(tmp
, undef_all_y_bits
), undef_y
));
599 undefGating(y
, yy
, undef_y
);
604 if (cell
->type
== "$mul")
606 std::vector
<int> a
= importDefSigSpec(cell
->connections
.at("\\A"), timestep
);
607 std::vector
<int> b
= importDefSigSpec(cell
->connections
.at("\\B"), timestep
);
608 std::vector
<int> y
= importDefSigSpec(cell
->connections
.at("\\Y"), timestep
);
609 extendSignalWidth(a
, b
, y
, cell
);
611 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
613 std::vector
<int> tmp(a
.size(), ez
->FALSE
);
614 for (int i
= 0; i
< int(a
.size()); i
++)
616 std::vector
<int> shifted_a(a
.size(), ez
->FALSE
);
617 for (int j
= i
; j
< int(a
.size()); j
++)
618 shifted_a
.at(j
) = a
.at(j
-i
);
619 tmp
= ez
->vec_ite(b
.at(i
), ez
->vec_add(tmp
, shifted_a
), tmp
);
621 ez
->assume(ez
->vec_eq(tmp
, yy
));
624 log_assert(arith_undef_handled
);
625 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
626 undefGating(y
, yy
, undef_y
);
631 if (cell
->type
== "$div" || cell
->type
== "$mod")
633 std::vector
<int> a
= importDefSigSpec(cell
->connections
.at("\\A"), timestep
);
634 std::vector
<int> b
= importDefSigSpec(cell
->connections
.at("\\B"), timestep
);
635 std::vector
<int> y
= importDefSigSpec(cell
->connections
.at("\\Y"), timestep
);
636 extendSignalWidth(a
, b
, y
, cell
);
638 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
640 std::vector
<int> a_u
, b_u
;
641 if (cell
->parameters
["\\A_SIGNED"].as_bool() && cell
->parameters
["\\B_SIGNED"].as_bool()) {
642 a_u
= ez
->vec_ite(a
.back(), ez
->vec_neg(a
), a
);
643 b_u
= ez
->vec_ite(b
.back(), ez
->vec_neg(b
), b
);
649 std::vector
<int> chain_buf
= a_u
;
650 std::vector
<int> y_u(a_u
.size(), ez
->FALSE
);
651 for (int i
= int(a
.size())-1; i
>= 0; i
--)
653 chain_buf
.insert(chain_buf
.end(), chain_buf
.size(), ez
->FALSE
);
655 std::vector
<int> b_shl(i
, ez
->FALSE
);
656 b_shl
.insert(b_shl
.end(), b_u
.begin(), b_u
.end());
657 b_shl
.insert(b_shl
.end(), chain_buf
.size()-b_shl
.size(), ez
->FALSE
);
659 y_u
.at(i
) = ez
->vec_ge_unsigned(chain_buf
, b_shl
);
660 chain_buf
= ez
->vec_ite(y_u
.at(i
), ez
->vec_sub(chain_buf
, b_shl
), chain_buf
);
662 chain_buf
.erase(chain_buf
.begin() + a_u
.size(), chain_buf
.end());
665 std::vector
<int> y_tmp
= ignore_div_by_zero
? yy
: ez
->vec_var(y
.size());
666 if (cell
->type
== "$div") {
667 if (cell
->parameters
["\\A_SIGNED"].as_bool() && cell
->parameters
["\\B_SIGNED"].as_bool())
668 ez
->assume(ez
->vec_eq(y_tmp
, ez
->vec_ite(ez
->XOR(a
.back(), b
.back()), ez
->vec_neg(y_u
), y_u
)));
670 ez
->assume(ez
->vec_eq(y_tmp
, y_u
));
672 if (cell
->parameters
["\\A_SIGNED"].as_bool() && cell
->parameters
["\\B_SIGNED"].as_bool())
673 ez
->assume(ez
->vec_eq(y_tmp
, ez
->vec_ite(a
.back(), ez
->vec_neg(chain_buf
), chain_buf
)));
675 ez
->assume(ez
->vec_eq(y_tmp
, chain_buf
));
678 if (ignore_div_by_zero
) {
679 ez
->assume(ez
->expression(ezSAT::OpOr
, b
));
681 std::vector
<int> div_zero_result
;
682 if (cell
->type
== "$div") {
683 if (cell
->parameters
["\\A_SIGNED"].as_bool() && cell
->parameters
["\\B_SIGNED"].as_bool()) {
684 std::vector
<int> all_ones(y
.size(), ez
->TRUE
);
685 std::vector
<int> only_first_one(y
.size(), ez
->FALSE
);
686 only_first_one
.at(0) = ez
->TRUE
;
687 div_zero_result
= ez
->vec_ite(a
.back(), only_first_one
, all_ones
);
689 div_zero_result
.insert(div_zero_result
.end(), cell
->connections
.at("\\A").width
, ez
->TRUE
);
690 div_zero_result
.insert(div_zero_result
.end(), y
.size() - div_zero_result
.size(), ez
->FALSE
);
693 int copy_a_bits
= std::min(cell
->connections
.at("\\A").width
, cell
->connections
.at("\\B").width
);
694 div_zero_result
.insert(div_zero_result
.end(), a
.begin(), a
.begin() + copy_a_bits
);
695 if (cell
->parameters
["\\A_SIGNED"].as_bool() && cell
->parameters
["\\B_SIGNED"].as_bool())
696 div_zero_result
.insert(div_zero_result
.end(), y
.size() - div_zero_result
.size(), div_zero_result
.back());
698 div_zero_result
.insert(div_zero_result
.end(), y
.size() - div_zero_result
.size(), ez
->FALSE
);
700 ez
->assume(ez
->vec_eq(yy
, ez
->vec_ite(ez
->expression(ezSAT::OpOr
, b
), y_tmp
, div_zero_result
)));
704 log_assert(arith_undef_handled
);
705 std::vector
<int> undef_y
= importUndefSigSpec(cell
->connections
.at("\\Y"), timestep
);
706 undefGating(y
, yy
, undef_y
);
711 if (timestep
> 0 && (cell
->type
== "$dff" || cell
->type
== "$_DFF_N_" || cell
->type
== "$_DFF_P_"))
715 initial_state
.add((*sigmap
)(cell
->connections
.at("\\Q")));
719 std::vector
<int> d
= importDefSigSpec(cell
->connections
.at("\\D"), timestep
-1);
720 std::vector
<int> q
= importDefSigSpec(cell
->connections
.at("\\Q"), timestep
);
722 std::vector
<int> qq
= model_undef
? ez
->vec_var(q
.size()) : q
;
723 ez
->assume(ez
->vec_eq(d
, qq
));
727 std::vector
<int> undef_d
= importUndefSigSpec(cell
->connections
.at("\\D"), timestep
-1);
728 std::vector
<int> undef_q
= importUndefSigSpec(cell
->connections
.at("\\Q"), timestep
);
730 ez
->assume(ez
->vec_eq(undef_d
, undef_q
));
731 undefGating(q
, qq
, undef_q
);
737 // Unsupported internal cell types: $pow $lut
738 // .. and all sequential cells except $dff and $_DFF_[NP]_