2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
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 #include "kernel/satgen.h"
21 #include "kernel/ff.h"
25 bool SatGen::importCell(RTLIL::Cell
*cell
, int timestep
)
27 bool arith_undef_handled
= false;
28 bool is_arith_compare
= cell
->type
.in(ID($lt
), ID($le
), ID($ge
), ID($gt
));
30 if (model_undef
&& (cell
->type
.in(ID($add
), ID($sub
), ID($mul
), ID($div
), ID($mod
), ID($divfloor
), ID($modfloor
)) || is_arith_compare
))
32 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
33 std::vector
<int> undef_b
= importUndefSigSpec(cell
->getPort(ID::B
), timestep
);
34 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
36 extendSignalWidth(undef_a
, undef_b
, cell
, true);
38 extendSignalWidth(undef_a
, undef_b
, undef_y
, cell
, true);
40 int undef_any_a
= ez
->expression(ezSAT::OpOr
, undef_a
);
41 int undef_any_b
= ez
->expression(ezSAT::OpOr
, undef_b
);
42 int undef_y_bit
= ez
->OR(undef_any_a
, undef_any_b
);
44 if (cell
->type
.in(ID($div
), ID($mod
), ID($divfloor
), ID($modfloor
))) {
45 std::vector
<int> b
= importSigSpec(cell
->getPort(ID::B
), timestep
);
46 undef_y_bit
= ez
->OR(undef_y_bit
, ez
->NOT(ez
->expression(ezSAT::OpOr
, b
)));
49 if (is_arith_compare
) {
50 for (size_t i
= 1; i
< undef_y
.size(); i
++)
51 ez
->SET(ez
->CONST_FALSE
, undef_y
.at(i
));
52 ez
->SET(undef_y_bit
, undef_y
.at(0));
54 std::vector
<int> undef_y_bits(undef_y
.size(), undef_y_bit
);
55 ez
->assume(ez
->vec_eq(undef_y_bits
, undef_y
));
58 arith_undef_handled
= true;
61 if (cell
->type
.in(ID($_AND_
), ID($_NAND_
), ID($_OR_
), ID($_NOR_
), ID($_XOR_
), ID($_XNOR_
), ID($_ANDNOT_
), ID($_ORNOT_
),
62 ID($
and), ID($
or), ID($
xor), ID($xnor
), ID($add
), ID($sub
)))
64 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
65 std::vector
<int> b
= importDefSigSpec(cell
->getPort(ID::B
), timestep
);
66 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
67 extendSignalWidth(a
, b
, y
, cell
);
69 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
71 if (cell
->type
.in(ID($
and), ID($_AND_
)))
72 ez
->assume(ez
->vec_eq(ez
->vec_and(a
, b
), yy
));
73 if (cell
->type
== ID($_NAND_
))
74 ez
->assume(ez
->vec_eq(ez
->vec_not(ez
->vec_and(a
, b
)), yy
));
75 if (cell
->type
.in(ID($
or), ID($_OR_
)))
76 ez
->assume(ez
->vec_eq(ez
->vec_or(a
, b
), yy
));
77 if (cell
->type
== ID($_NOR_
))
78 ez
->assume(ez
->vec_eq(ez
->vec_not(ez
->vec_or(a
, b
)), yy
));
79 if (cell
->type
.in(ID($
xor), ID($_XOR_
)))
80 ez
->assume(ez
->vec_eq(ez
->vec_xor(a
, b
), yy
));
81 if (cell
->type
.in(ID($xnor
), ID($_XNOR_
)))
82 ez
->assume(ez
->vec_eq(ez
->vec_not(ez
->vec_xor(a
, b
)), yy
));
83 if (cell
->type
== ID($_ANDNOT_
))
84 ez
->assume(ez
->vec_eq(ez
->vec_and(a
, ez
->vec_not(b
)), yy
));
85 if (cell
->type
== ID($_ORNOT_
))
86 ez
->assume(ez
->vec_eq(ez
->vec_or(a
, ez
->vec_not(b
)), yy
));
87 if (cell
->type
== ID($add
))
88 ez
->assume(ez
->vec_eq(ez
->vec_add(a
, b
), yy
));
89 if (cell
->type
== ID($sub
))
90 ez
->assume(ez
->vec_eq(ez
->vec_sub(a
, b
), yy
));
92 if (model_undef
&& !arith_undef_handled
)
94 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
95 std::vector
<int> undef_b
= importUndefSigSpec(cell
->getPort(ID::B
), timestep
);
96 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
97 extendSignalWidth(undef_a
, undef_b
, undef_y
, cell
, false);
99 if (cell
->type
.in(ID($
and), ID($_AND_
), ID($_NAND_
))) {
100 std::vector
<int> a0
= ez
->vec_and(ez
->vec_not(a
), ez
->vec_not(undef_a
));
101 std::vector
<int> b0
= ez
->vec_and(ez
->vec_not(b
), ez
->vec_not(undef_b
));
102 std::vector
<int> yX
= ez
->vec_and(ez
->vec_or(undef_a
, undef_b
), ez
->vec_not(ez
->vec_or(a0
, b0
)));
103 ez
->assume(ez
->vec_eq(yX
, undef_y
));
105 else if (cell
->type
.in(ID($
or), ID($_OR_
), ID($_NOR_
))) {
106 std::vector
<int> a1
= ez
->vec_and(a
, ez
->vec_not(undef_a
));
107 std::vector
<int> b1
= ez
->vec_and(b
, ez
->vec_not(undef_b
));
108 std::vector
<int> yX
= ez
->vec_and(ez
->vec_or(undef_a
, undef_b
), ez
->vec_not(ez
->vec_or(a1
, b1
)));
109 ez
->assume(ez
->vec_eq(yX
, undef_y
));
111 else if (cell
->type
.in(ID($
xor), ID($xnor
), ID($_XOR_
), ID($_XNOR_
))) {
112 std::vector
<int> yX
= ez
->vec_or(undef_a
, undef_b
);
113 ez
->assume(ez
->vec_eq(yX
, undef_y
));
115 else if (cell
->type
== ID($_ANDNOT_
)) {
116 std::vector
<int> a0
= ez
->vec_and(ez
->vec_not(a
), ez
->vec_not(undef_a
));
117 std::vector
<int> b1
= ez
->vec_and(b
, ez
->vec_not(undef_b
));
118 std::vector
<int> yX
= ez
->vec_and(ez
->vec_or(undef_a
, undef_b
), ez
->vec_not(ez
->vec_or(a0
, b1
)));
119 ez
->assume(ez
->vec_eq(yX
, undef_y
));
122 else if (cell
->type
== ID($_ORNOT_
)) {
123 std::vector
<int> a1
= ez
->vec_and(a
, ez
->vec_not(undef_a
));
124 std::vector
<int> b0
= ez
->vec_and(ez
->vec_not(b
), ez
->vec_not(undef_b
));
125 std::vector
<int> yX
= ez
->vec_and(ez
->vec_or(undef_a
, undef_b
), ez
->vec_not(ez
->vec_or(a1
, b0
)));
126 ez
->assume(ez
->vec_eq(yX
, undef_y
));
131 undefGating(y
, yy
, undef_y
);
133 else if (model_undef
)
135 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
136 undefGating(y
, yy
, undef_y
);
141 if (cell
->type
.in(ID($_AOI3_
), ID($_OAI3_
), ID($_AOI4_
), ID($_OAI4_
)))
143 bool aoi_mode
= cell
->type
.in(ID($_AOI3_
), ID($_AOI4_
));
144 bool three_mode
= cell
->type
.in(ID($_AOI3_
), ID($_OAI3_
));
146 int a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
).at(0);
147 int b
= importDefSigSpec(cell
->getPort(ID::B
), timestep
).at(0);
148 int c
= importDefSigSpec(cell
->getPort(ID::C
), timestep
).at(0);
149 int d
= three_mode
? (aoi_mode
? ez
->CONST_TRUE
: ez
->CONST_FALSE
) : importDefSigSpec(cell
->getPort(ID::D
), timestep
).at(0);
150 int y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
).at(0);
151 int yy
= model_undef
? ez
->literal() : y
;
153 if (cell
->type
.in(ID($_AOI3_
), ID($_AOI4_
)))
154 ez
->assume(ez
->IFF(ez
->NOT(ez
->OR(ez
->AND(a
, b
), ez
->AND(c
, d
))), yy
));
156 ez
->assume(ez
->IFF(ez
->NOT(ez
->AND(ez
->OR(a
, b
), ez
->OR(c
, d
))), yy
));
160 int undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
).at(0);
161 int undef_b
= importUndefSigSpec(cell
->getPort(ID::B
), timestep
).at(0);
162 int undef_c
= importUndefSigSpec(cell
->getPort(ID::C
), timestep
).at(0);
163 int undef_d
= three_mode
? ez
->CONST_FALSE
: importUndefSigSpec(cell
->getPort(ID::D
), timestep
).at(0);
164 int undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
).at(0);
168 int a0
= ez
->AND(ez
->NOT(a
), ez
->NOT(undef_a
));
169 int b0
= ez
->AND(ez
->NOT(b
), ez
->NOT(undef_b
));
170 int c0
= ez
->AND(ez
->NOT(c
), ez
->NOT(undef_c
));
171 int d0
= ez
->AND(ez
->NOT(d
), ez
->NOT(undef_d
));
173 int ab
= ez
->AND(a
, b
), cd
= ez
->AND(c
, d
);
174 int undef_ab
= ez
->AND(ez
->OR(undef_a
, undef_b
), ez
->NOT(ez
->OR(a0
, b0
)));
175 int undef_cd
= ez
->AND(ez
->OR(undef_c
, undef_d
), ez
->NOT(ez
->OR(c0
, d0
)));
177 int ab1
= ez
->AND(ab
, ez
->NOT(undef_ab
));
178 int cd1
= ez
->AND(cd
, ez
->NOT(undef_cd
));
179 int yX
= ez
->AND(ez
->OR(undef_ab
, undef_cd
), ez
->NOT(ez
->OR(ab1
, cd1
)));
181 ez
->assume(ez
->IFF(yX
, undef_y
));
185 int a1
= ez
->AND(a
, ez
->NOT(undef_a
));
186 int b1
= ez
->AND(b
, ez
->NOT(undef_b
));
187 int c1
= ez
->AND(c
, ez
->NOT(undef_c
));
188 int d1
= ez
->AND(d
, ez
->NOT(undef_d
));
190 int ab
= ez
->OR(a
, b
), cd
= ez
->OR(c
, d
);
191 int undef_ab
= ez
->AND(ez
->OR(undef_a
, undef_b
), ez
->NOT(ez
->OR(a1
, b1
)));
192 int undef_cd
= ez
->AND(ez
->OR(undef_c
, undef_d
), ez
->NOT(ez
->OR(c1
, d1
)));
194 int ab0
= ez
->AND(ez
->NOT(ab
), ez
->NOT(undef_ab
));
195 int cd0
= ez
->AND(ez
->NOT(cd
), ez
->NOT(undef_cd
));
196 int yX
= ez
->AND(ez
->OR(undef_ab
, undef_cd
), ez
->NOT(ez
->OR(ab0
, cd0
)));
198 ez
->assume(ez
->IFF(yX
, undef_y
));
201 undefGating(y
, yy
, undef_y
);
207 if (cell
->type
.in(ID($_NOT_
), ID($
not)))
209 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
210 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
211 extendSignalWidthUnary(a
, y
, cell
);
213 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
214 ez
->assume(ez
->vec_eq(ez
->vec_not(a
), yy
));
217 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
218 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
219 extendSignalWidthUnary(undef_a
, undef_y
, cell
, false);
220 ez
->assume(ez
->vec_eq(undef_a
, undef_y
));
221 undefGating(y
, yy
, undef_y
);
226 if (cell
->type
.in(ID($_MUX_
), ID($mux
), ID($_NMUX_
)))
228 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
229 std::vector
<int> b
= importDefSigSpec(cell
->getPort(ID::B
), timestep
);
230 std::vector
<int> s
= importDefSigSpec(cell
->getPort(ID::S
), timestep
);
231 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
233 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
234 if (cell
->type
== ID($_NMUX_
))
235 ez
->assume(ez
->vec_eq(ez
->vec_not(ez
->vec_ite(s
.at(0), b
, a
)), yy
));
237 ez
->assume(ez
->vec_eq(ez
->vec_ite(s
.at(0), b
, a
), yy
));
241 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
242 std::vector
<int> undef_b
= importUndefSigSpec(cell
->getPort(ID::B
), timestep
);
243 std::vector
<int> undef_s
= importUndefSigSpec(cell
->getPort(ID::S
), timestep
);
244 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
246 std::vector
<int> unequal_ab
= ez
->vec_not(ez
->vec_iff(a
, b
));
247 std::vector
<int> undef_ab
= ez
->vec_or(unequal_ab
, ez
->vec_or(undef_a
, undef_b
));
248 std::vector
<int> yX
= ez
->vec_ite(undef_s
.at(0), undef_ab
, ez
->vec_ite(s
.at(0), undef_b
, undef_a
));
249 ez
->assume(ez
->vec_eq(yX
, undef_y
));
250 undefGating(y
, yy
, undef_y
);
255 if (cell
->type
== ID($bmux
))
257 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
258 std::vector
<int> s
= importDefSigSpec(cell
->getPort(ID::S
), timestep
);
259 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
260 std::vector
<int> undef_a
, undef_s
, undef_y
;
264 undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
265 undef_s
= importUndefSigSpec(cell
->getPort(ID::S
), timestep
);
266 undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
269 if (GetSize(s
) == 0) {
272 ez
->vec_set(undef_a
, undef_y
);
274 for (int i
= GetSize(s
)-1; i
>= 0; i
--)
276 std::vector
<int> out
= (i
== 0) ? y
: ez
->vec_var(a
.size() / 2);
277 std::vector
<int> yy
= model_undef
? ez
->vec_var(out
.size()) : out
;
279 std::vector
<int> a0(a
.begin(), a
.begin() + a
.size() / 2);
280 std::vector
<int> a1(a
.begin() + a
.size() / 2, a
.end());
281 ez
->assume(ez
->vec_eq(ez
->vec_ite(s
.at(i
), a1
, a0
), yy
));
285 std::vector
<int> undef_out
= (i
== 0) ? undef_y
: ez
->vec_var(a
.size() / 2);
286 std::vector
<int> undef_a0(undef_a
.begin(), undef_a
.begin() + a
.size() / 2);
287 std::vector
<int> undef_a1(undef_a
.begin() + a
.size() / 2, undef_a
.end());
288 std::vector
<int> unequal_ab
= ez
->vec_not(ez
->vec_iff(a0
, a1
));
289 std::vector
<int> undef_ab
= ez
->vec_or(unequal_ab
, ez
->vec_or(undef_a0
, undef_a1
));
290 std::vector
<int> yX
= ez
->vec_ite(undef_s
.at(i
), undef_ab
, ez
->vec_ite(s
.at(i
), undef_a1
, undef_a0
));
291 ez
->assume(ez
->vec_eq(yX
, undef_out
));
292 undefGating(out
, yy
, undef_out
);
303 if (cell
->type
== ID($demux
))
305 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
306 std::vector
<int> s
= importDefSigSpec(cell
->getPort(ID::S
), timestep
);
307 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
308 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
309 std::vector
<int> undef_a
, undef_s
, undef_y
;
313 undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
314 undef_s
= importUndefSigSpec(cell
->getPort(ID::S
), timestep
);
315 undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
318 if (GetSize(s
) == 0) {
321 ez
->vec_set(undef_a
, undef_y
);
323 for (int i
= 0; i
< (1 << GetSize(s
)); i
++)
326 for (int j
= 0; j
< GetSize(s
); j
++) {
330 ss
.push_back(ez
->NOT(s
[j
]));
332 int sss
= ez
->expression(ezSAT::OpAnd
, ss
);
334 for (int j
= 0; j
< GetSize(a
); j
++) {
335 ez
->SET(ez
->AND(sss
, a
[j
]), yy
.at(i
* GetSize(a
) + j
));
340 int s0
= ez
->expression(ezSAT::OpOr
, ez
->vec_and(ez
->vec_not(ss
), ez
->vec_not(undef_s
)));
341 int us
= ez
->AND(ez
->NOT(s0
), ez
->expression(ezSAT::OpOr
, undef_s
));
342 for (int j
= 0; j
< GetSize(a
); j
++) {
343 int a0
= ez
->AND(ez
->NOT(a
[j
]), ez
->NOT(undef_a
[j
]));
344 int yX
= ez
->AND(ez
->OR(us
, undef_a
[j
]), ez
->NOT(ez
->OR(s0
, a0
)));
345 ez
->SET(yX
, undef_y
.at(i
* GetSize(a
) + j
));
350 undefGating(y
, yy
, undef_y
);
355 if (cell
->type
== ID($pmux
))
357 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
358 std::vector
<int> b
= importDefSigSpec(cell
->getPort(ID::B
), timestep
);
359 std::vector
<int> s
= importDefSigSpec(cell
->getPort(ID::S
), timestep
);
360 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
362 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
364 std::vector
<int> tmp
= a
;
365 for (size_t i
= 0; i
< s
.size(); i
++) {
366 std::vector
<int> part_of_b(b
.begin()+i
*a
.size(), b
.begin()+(i
+1)*a
.size());
367 tmp
= ez
->vec_ite(s
.at(i
), part_of_b
, tmp
);
369 ez
->assume(ez
->vec_eq(tmp
, yy
));
373 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
374 std::vector
<int> undef_b
= importUndefSigSpec(cell
->getPort(ID::B
), timestep
);
375 std::vector
<int> undef_s
= importUndefSigSpec(cell
->getPort(ID::S
), timestep
);
376 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
378 int maybe_a
= ez
->CONST_TRUE
;
380 std::vector
<int> bits_set
= std::vector
<int>(undef_y
.size(), ez
->CONST_FALSE
);
381 std::vector
<int> bits_clr
= std::vector
<int>(undef_y
.size(), ez
->CONST_FALSE
);
383 for (size_t i
= 0; i
< s
.size(); i
++)
385 std::vector
<int> part_of_b(b
.begin()+i
*a
.size(), b
.begin()+(i
+1)*a
.size());
386 std::vector
<int> part_of_undef_b(undef_b
.begin()+i
*a
.size(), undef_b
.begin()+(i
+1)*a
.size());
388 int maybe_s
= ez
->OR(s
.at(i
), undef_s
.at(i
));
389 int sure_s
= ez
->AND(s
.at(i
), ez
->NOT(undef_s
.at(i
)));
391 maybe_a
= ez
->AND(maybe_a
, ez
->NOT(sure_s
));
393 bits_set
= ez
->vec_ite(maybe_s
, ez
->vec_or(bits_set
, ez
->vec_or(part_of_b
, part_of_undef_b
)), bits_set
);
394 bits_clr
= ez
->vec_ite(maybe_s
, ez
->vec_or(bits_clr
, ez
->vec_or(ez
->vec_not(part_of_b
), part_of_undef_b
)), bits_clr
);
397 bits_set
= ez
->vec_ite(maybe_a
, ez
->vec_or(bits_set
, ez
->vec_or(bits_set
, ez
->vec_or(a
, undef_a
))), bits_set
);
398 bits_clr
= ez
->vec_ite(maybe_a
, ez
->vec_or(bits_clr
, ez
->vec_or(bits_clr
, ez
->vec_or(ez
->vec_not(a
), undef_a
))), bits_clr
);
400 ez
->assume(ez
->vec_eq(ez
->vec_not(ez
->vec_xor(bits_set
, bits_clr
)), undef_y
));
401 undefGating(y
, yy
, undef_y
);
406 if (cell
->type
.in(ID($pos
), ID($neg
)))
408 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
409 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
410 extendSignalWidthUnary(a
, y
, cell
);
412 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
414 if (cell
->type
== ID($pos
)) {
415 ez
->assume(ez
->vec_eq(a
, yy
));
417 std::vector
<int> zero(a
.size(), ez
->CONST_FALSE
);
418 ez
->assume(ez
->vec_eq(ez
->vec_sub(zero
, a
), yy
));
423 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
424 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
425 extendSignalWidthUnary(undef_a
, undef_y
, cell
);
427 if (cell
->type
== ID($pos
)) {
428 ez
->assume(ez
->vec_eq(undef_a
, undef_y
));
430 int undef_any_a
= ez
->expression(ezSAT::OpOr
, undef_a
);
431 std::vector
<int> undef_y_bits(undef_y
.size(), undef_any_a
);
432 ez
->assume(ez
->vec_eq(undef_y_bits
, undef_y
));
435 undefGating(y
, yy
, undef_y
);
440 if (cell
->type
.in(ID($reduce_and
), ID($reduce_or
), ID($reduce_xor
), ID($reduce_xnor
), ID($reduce_bool
), ID($logic_not
)))
442 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
443 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
445 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
447 if (cell
->type
== ID($reduce_and
))
448 ez
->SET(ez
->expression(ez
->OpAnd
, a
), yy
.at(0));
449 if (cell
->type
.in(ID($reduce_or
), ID($reduce_bool
)))
450 ez
->SET(ez
->expression(ez
->OpOr
, a
), yy
.at(0));
451 if (cell
->type
== ID($reduce_xor
))
452 ez
->SET(ez
->expression(ez
->OpXor
, a
), yy
.at(0));
453 if (cell
->type
== ID($reduce_xnor
))
454 ez
->SET(ez
->NOT(ez
->expression(ez
->OpXor
, a
)), yy
.at(0));
455 if (cell
->type
== ID($logic_not
))
456 ez
->SET(ez
->NOT(ez
->expression(ez
->OpOr
, a
)), yy
.at(0));
457 for (size_t i
= 1; i
< y
.size(); i
++)
458 ez
->SET(ez
->CONST_FALSE
, yy
.at(i
));
462 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
463 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
464 int aX
= ez
->expression(ezSAT::OpOr
, undef_a
);
466 if (cell
->type
== ID($reduce_and
)) {
467 int a0
= ez
->expression(ezSAT::OpOr
, ez
->vec_and(ez
->vec_not(a
), ez
->vec_not(undef_a
)));
468 ez
->assume(ez
->IFF(ez
->AND(ez
->NOT(a0
), aX
), undef_y
.at(0)));
470 else if (cell
->type
.in(ID($reduce_or
), ID($reduce_bool
), ID($logic_not
))) {
471 int a1
= ez
->expression(ezSAT::OpOr
, ez
->vec_and(a
, ez
->vec_not(undef_a
)));
472 ez
->assume(ez
->IFF(ez
->AND(ez
->NOT(a1
), aX
), undef_y
.at(0)));
474 else if (cell
->type
.in(ID($reduce_xor
), ID($reduce_xnor
))) {
475 ez
->assume(ez
->IFF(aX
, undef_y
.at(0)));
479 for (size_t i
= 1; i
< undef_y
.size(); i
++)
480 ez
->SET(ez
->CONST_FALSE
, undef_y
.at(i
));
482 undefGating(y
, yy
, undef_y
);
487 if (cell
->type
.in(ID($logic_and
), ID($logic_or
)))
489 std::vector
<int> vec_a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
490 std::vector
<int> vec_b
= importDefSigSpec(cell
->getPort(ID::B
), timestep
);
492 int a
= ez
->expression(ez
->OpOr
, vec_a
);
493 int b
= ez
->expression(ez
->OpOr
, vec_b
);
494 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
496 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
498 if (cell
->type
== ID($logic_and
))
499 ez
->SET(ez
->expression(ez
->OpAnd
, a
, b
), yy
.at(0));
501 ez
->SET(ez
->expression(ez
->OpOr
, a
, b
), yy
.at(0));
502 for (size_t i
= 1; i
< y
.size(); i
++)
503 ez
->SET(ez
->CONST_FALSE
, yy
.at(i
));
507 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
508 std::vector
<int> undef_b
= importUndefSigSpec(cell
->getPort(ID::B
), timestep
);
509 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
511 int a0
= ez
->NOT(ez
->OR(ez
->expression(ezSAT::OpOr
, vec_a
), ez
->expression(ezSAT::OpOr
, undef_a
)));
512 int b0
= ez
->NOT(ez
->OR(ez
->expression(ezSAT::OpOr
, vec_b
), ez
->expression(ezSAT::OpOr
, undef_b
)));
513 int a1
= ez
->expression(ezSAT::OpOr
, ez
->vec_and(vec_a
, ez
->vec_not(undef_a
)));
514 int b1
= ez
->expression(ezSAT::OpOr
, ez
->vec_and(vec_b
, ez
->vec_not(undef_b
)));
515 int aX
= ez
->expression(ezSAT::OpOr
, undef_a
);
516 int bX
= ez
->expression(ezSAT::OpOr
, undef_b
);
518 if (cell
->type
== ID($logic_and
))
519 ez
->SET(ez
->AND(ez
->OR(aX
, bX
), ez
->NOT(ez
->AND(a1
, b1
)), ez
->NOT(a0
), ez
->NOT(b0
)), undef_y
.at(0));
520 else if (cell
->type
== ID($logic_or
))
521 ez
->SET(ez
->AND(ez
->OR(aX
, bX
), ez
->NOT(ez
->AND(a0
, b0
)), ez
->NOT(a1
), ez
->NOT(b1
)), undef_y
.at(0));
525 for (size_t i
= 1; i
< undef_y
.size(); i
++)
526 ez
->SET(ez
->CONST_FALSE
, undef_y
.at(i
));
528 undefGating(y
, yy
, undef_y
);
533 if (cell
->type
.in(ID($lt
), ID($le
), ID($eq
), ID($ne
), ID($eqx
), ID($nex
), ID($ge
), ID($gt
)))
535 bool is_signed
= cell
->parameters
[ID::A_SIGNED
].as_bool() && cell
->parameters
[ID::B_SIGNED
].as_bool();
536 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
537 std::vector
<int> b
= importDefSigSpec(cell
->getPort(ID::B
), timestep
);
538 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
539 extendSignalWidth(a
, b
, cell
);
541 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
543 if (model_undef
&& cell
->type
.in(ID($eqx
), ID($nex
))) {
544 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
545 std::vector
<int> undef_b
= importUndefSigSpec(cell
->getPort(ID::B
), timestep
);
546 extendSignalWidth(undef_a
, undef_b
, cell
, true);
547 a
= ez
->vec_or(a
, undef_a
);
548 b
= ez
->vec_or(b
, undef_b
);
551 if (cell
->type
== ID($lt
))
552 ez
->SET(is_signed
? ez
->vec_lt_signed(a
, b
) : ez
->vec_lt_unsigned(a
, b
), yy
.at(0));
553 if (cell
->type
== ID($le
))
554 ez
->SET(is_signed
? ez
->vec_le_signed(a
, b
) : ez
->vec_le_unsigned(a
, b
), yy
.at(0));
555 if (cell
->type
.in(ID($eq
), ID($eqx
)))
556 ez
->SET(ez
->vec_eq(a
, b
), yy
.at(0));
557 if (cell
->type
.in(ID($ne
), ID($nex
)))
558 ez
->SET(ez
->vec_ne(a
, b
), yy
.at(0));
559 if (cell
->type
== ID($ge
))
560 ez
->SET(is_signed
? ez
->vec_ge_signed(a
, b
) : ez
->vec_ge_unsigned(a
, b
), yy
.at(0));
561 if (cell
->type
== ID($gt
))
562 ez
->SET(is_signed
? ez
->vec_gt_signed(a
, b
) : ez
->vec_gt_unsigned(a
, b
), yy
.at(0));
563 for (size_t i
= 1; i
< y
.size(); i
++)
564 ez
->SET(ez
->CONST_FALSE
, yy
.at(i
));
566 if (model_undef
&& cell
->type
.in(ID($eqx
), ID($nex
)))
568 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
569 std::vector
<int> undef_b
= importUndefSigSpec(cell
->getPort(ID::B
), timestep
);
570 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
571 extendSignalWidth(undef_a
, undef_b
, cell
, true);
573 if (cell
->type
== ID($eqx
))
574 yy
.at(0) = ez
->AND(yy
.at(0), ez
->vec_eq(undef_a
, undef_b
));
576 yy
.at(0) = ez
->OR(yy
.at(0), ez
->vec_ne(undef_a
, undef_b
));
578 for (size_t i
= 0; i
< y
.size(); i
++)
579 ez
->SET(ez
->CONST_FALSE
, undef_y
.at(i
));
581 ez
->assume(ez
->vec_eq(y
, yy
));
583 else if (model_undef
&& cell
->type
.in(ID($eq
), ID($ne
)))
585 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
586 std::vector
<int> undef_b
= importUndefSigSpec(cell
->getPort(ID::B
), timestep
);
587 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
588 extendSignalWidth(undef_a
, undef_b
, cell
, true);
590 int undef_any_a
= ez
->expression(ezSAT::OpOr
, undef_a
);
591 int undef_any_b
= ez
->expression(ezSAT::OpOr
, undef_b
);
592 int undef_any
= ez
->OR(undef_any_a
, undef_any_b
);
594 std::vector
<int> masked_a_bits
= ez
->vec_or(a
, ez
->vec_or(undef_a
, undef_b
));
595 std::vector
<int> masked_b_bits
= ez
->vec_or(b
, ez
->vec_or(undef_a
, undef_b
));
597 int masked_ne
= ez
->vec_ne(masked_a_bits
, masked_b_bits
);
598 int undef_y_bit
= ez
->AND(undef_any
, ez
->NOT(masked_ne
));
600 for (size_t i
= 1; i
< undef_y
.size(); i
++)
601 ez
->SET(ez
->CONST_FALSE
, undef_y
.at(i
));
602 ez
->SET(undef_y_bit
, undef_y
.at(0));
604 undefGating(y
, yy
, undef_y
);
609 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
610 undefGating(y
, yy
, undef_y
);
612 log_assert(!model_undef
|| arith_undef_handled
);
617 if (cell
->type
.in(ID($shl
), ID($shr
), ID($sshl
), ID($sshr
), ID($shift
), ID($shiftx
)))
619 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
620 std::vector
<int> b
= importDefSigSpec(cell
->getPort(ID::B
), timestep
);
621 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
623 int extend_bit
= ez
->CONST_FALSE
;
625 if (cell
->parameters
[ID::A_SIGNED
].as_bool())
626 extend_bit
= a
.back();
628 while (y
.size() < a
.size())
629 y
.push_back(ez
->literal());
630 while (y
.size() > a
.size())
631 a
.push_back(extend_bit
);
633 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
634 std::vector
<int> shifted_a
;
636 if (cell
->type
.in( ID($shl
), ID($sshl
)))
637 shifted_a
= ez
->vec_shift_left(a
, b
, false, ez
->CONST_FALSE
, ez
->CONST_FALSE
);
639 if (cell
->type
== ID($shr
))
640 shifted_a
= ez
->vec_shift_right(a
, b
, false, ez
->CONST_FALSE
, ez
->CONST_FALSE
);
642 if (cell
->type
== ID($sshr
))
643 shifted_a
= ez
->vec_shift_right(a
, b
, false, cell
->parameters
[ID::A_SIGNED
].as_bool() ? a
.back() : ez
->CONST_FALSE
, ez
->CONST_FALSE
);
645 if (cell
->type
.in(ID($shift
), ID($shiftx
)))
646 shifted_a
= ez
->vec_shift_right(a
, b
, cell
->parameters
[ID::B_SIGNED
].as_bool(), ez
->CONST_FALSE
, ez
->CONST_FALSE
);
648 ez
->assume(ez
->vec_eq(shifted_a
, yy
));
652 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
653 std::vector
<int> undef_b
= importUndefSigSpec(cell
->getPort(ID::B
), timestep
);
654 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
655 std::vector
<int> undef_a_shifted
;
657 extend_bit
= cell
->type
== ID($shiftx
) ? ez
->CONST_TRUE
: ez
->CONST_FALSE
;
658 if (cell
->parameters
[ID::A_SIGNED
].as_bool())
659 extend_bit
= undef_a
.back();
661 while (undef_y
.size() < undef_a
.size())
662 undef_y
.push_back(ez
->literal());
663 while (undef_y
.size() > undef_a
.size())
664 undef_a
.push_back(extend_bit
);
666 if (cell
->type
.in(ID($shl
), ID($sshl
)))
667 undef_a_shifted
= ez
->vec_shift_left(undef_a
, b
, false, ez
->CONST_FALSE
, ez
->CONST_FALSE
);
669 if (cell
->type
== ID($shr
))
670 undef_a_shifted
= ez
->vec_shift_right(undef_a
, b
, false, ez
->CONST_FALSE
, ez
->CONST_FALSE
);
672 if (cell
->type
== ID($sshr
))
673 undef_a_shifted
= ez
->vec_shift_right(undef_a
, b
, false, cell
->parameters
[ID::A_SIGNED
].as_bool() ? undef_a
.back() : ez
->CONST_FALSE
, ez
->CONST_FALSE
);
675 if (cell
->type
== ID($shift
))
676 undef_a_shifted
= ez
->vec_shift_right(undef_a
, b
, cell
->parameters
[ID::B_SIGNED
].as_bool(), ez
->CONST_FALSE
, ez
->CONST_FALSE
);
678 if (cell
->type
== ID($shiftx
))
679 undef_a_shifted
= ez
->vec_shift_right(undef_a
, b
, cell
->parameters
[ID::B_SIGNED
].as_bool(), ez
->CONST_TRUE
, ez
->CONST_TRUE
);
681 int undef_any_b
= ez
->expression(ezSAT::OpOr
, undef_b
);
682 std::vector
<int> undef_all_y_bits(undef_y
.size(), undef_any_b
);
683 ez
->assume(ez
->vec_eq(ez
->vec_or(undef_a_shifted
, undef_all_y_bits
), undef_y
));
684 undefGating(y
, yy
, undef_y
);
689 if (cell
->type
== ID($mul
))
691 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
692 std::vector
<int> b
= importDefSigSpec(cell
->getPort(ID::B
), timestep
);
693 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
694 extendSignalWidth(a
, b
, y
, cell
);
696 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
698 std::vector
<int> tmp(a
.size(), ez
->CONST_FALSE
);
699 for (int i
= 0; i
< int(a
.size()); i
++)
701 std::vector
<int> shifted_a(a
.size(), ez
->CONST_FALSE
);
702 for (int j
= i
; j
< int(a
.size()); j
++)
703 shifted_a
.at(j
) = a
.at(j
-i
);
704 tmp
= ez
->vec_ite(b
.at(i
), ez
->vec_add(tmp
, shifted_a
), tmp
);
706 ez
->assume(ez
->vec_eq(tmp
, yy
));
709 log_assert(arith_undef_handled
);
710 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
711 undefGating(y
, yy
, undef_y
);
716 if (cell
->type
== ID($macc
))
718 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
719 std::vector
<int> b
= importDefSigSpec(cell
->getPort(ID::B
), timestep
);
720 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
723 macc
.from_cell(cell
);
725 std::vector
<int> tmp(GetSize(y
), ez
->CONST_FALSE
);
727 for (auto &port
: macc
.ports
)
729 std::vector
<int> in_a
= importDefSigSpec(port
.in_a
, timestep
);
730 std::vector
<int> in_b
= importDefSigSpec(port
.in_b
, timestep
);
732 while (GetSize(in_a
) < GetSize(y
))
733 in_a
.push_back(port
.is_signed
&& !in_a
.empty() ? in_a
.back() : ez
->CONST_FALSE
);
734 in_a
.resize(GetSize(y
));
738 while (GetSize(in_b
) < GetSize(y
))
739 in_b
.push_back(port
.is_signed
&& !in_b
.empty() ? in_b
.back() : ez
->CONST_FALSE
);
740 in_b
.resize(GetSize(y
));
742 for (int i
= 0; i
< GetSize(in_b
); i
++) {
743 std::vector
<int> shifted_a(in_a
.size(), ez
->CONST_FALSE
);
744 for (int j
= i
; j
< int(in_a
.size()); j
++)
745 shifted_a
.at(j
) = in_a
.at(j
-i
);
746 if (port
.do_subtract
)
747 tmp
= ez
->vec_ite(in_b
.at(i
), ez
->vec_sub(tmp
, shifted_a
), tmp
);
749 tmp
= ez
->vec_ite(in_b
.at(i
), ez
->vec_add(tmp
, shifted_a
), tmp
);
754 if (port
.do_subtract
)
755 tmp
= ez
->vec_sub(tmp
, in_a
);
757 tmp
= ez
->vec_add(tmp
, in_a
);
761 for (int i
= 0; i
< GetSize(b
); i
++) {
762 std::vector
<int> val(GetSize(y
), ez
->CONST_FALSE
);
764 tmp
= ez
->vec_add(tmp
, val
);
769 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
770 std::vector
<int> undef_b
= importUndefSigSpec(cell
->getPort(ID::B
), timestep
);
772 int undef_any_a
= ez
->expression(ezSAT::OpOr
, undef_a
);
773 int undef_any_b
= ez
->expression(ezSAT::OpOr
, undef_b
);
775 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
776 ez
->assume(ez
->vec_eq(undef_y
, std::vector
<int>(GetSize(y
), ez
->OR(undef_any_a
, undef_any_b
))));
778 undefGating(y
, tmp
, undef_y
);
781 ez
->assume(ez
->vec_eq(y
, tmp
));
786 if (cell
->type
.in(ID($div
), ID($mod
), ID($divfloor
), ID($modfloor
)))
788 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
789 std::vector
<int> b
= importDefSigSpec(cell
->getPort(ID::B
), timestep
);
790 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
791 extendSignalWidth(a
, b
, y
, cell
);
793 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
795 std::vector
<int> a_u
, b_u
;
796 if (cell
->parameters
[ID::A_SIGNED
].as_bool() && cell
->parameters
[ID::B_SIGNED
].as_bool()) {
797 a_u
= ez
->vec_ite(a
.back(), ez
->vec_neg(a
), a
);
798 b_u
= ez
->vec_ite(b
.back(), ez
->vec_neg(b
), b
);
804 std::vector
<int> chain_buf
= a_u
;
805 std::vector
<int> y_u(a_u
.size(), ez
->CONST_FALSE
);
806 for (int i
= int(a
.size())-1; i
>= 0; i
--)
808 chain_buf
.insert(chain_buf
.end(), chain_buf
.size(), ez
->CONST_FALSE
);
810 std::vector
<int> b_shl(i
, ez
->CONST_FALSE
);
811 b_shl
.insert(b_shl
.end(), b_u
.begin(), b_u
.end());
812 b_shl
.insert(b_shl
.end(), chain_buf
.size()-b_shl
.size(), ez
->CONST_FALSE
);
814 y_u
.at(i
) = ez
->vec_ge_unsigned(chain_buf
, b_shl
);
815 chain_buf
= ez
->vec_ite(y_u
.at(i
), ez
->vec_sub(chain_buf
, b_shl
), chain_buf
);
817 chain_buf
.erase(chain_buf
.begin() + a_u
.size(), chain_buf
.end());
820 std::vector
<int> y_tmp
= ignore_div_by_zero
? yy
: ez
->vec_var(y
.size());
822 // modulo calculation
823 std::vector
<int> modulo_trunc
;
824 int floored_eq_trunc
;
825 if (cell
->parameters
[ID::A_SIGNED
].as_bool() && cell
->parameters
[ID::B_SIGNED
].as_bool()) {
826 modulo_trunc
= ez
->vec_ite(a
.back(), ez
->vec_neg(chain_buf
), chain_buf
);
827 // floor == trunc when sgn(a) == sgn(b) or trunc == 0
828 floored_eq_trunc
= ez
->OR(ez
->IFF(a
.back(), b
.back()), ez
->NOT(ez
->expression(ezSAT::OpOr
, modulo_trunc
)));
830 modulo_trunc
= chain_buf
;
831 floored_eq_trunc
= ez
->CONST_TRUE
;
834 if (cell
->type
== ID($div
)) {
835 if (cell
->parameters
[ID::A_SIGNED
].as_bool() && cell
->parameters
[ID::B_SIGNED
].as_bool())
836 ez
->assume(ez
->vec_eq(y_tmp
, ez
->vec_ite(ez
->XOR(a
.back(), b
.back()), ez
->vec_neg(y_u
), y_u
)));
838 ez
->assume(ez
->vec_eq(y_tmp
, y_u
));
839 } else if (cell
->type
== ID($mod
)) {
840 ez
->assume(ez
->vec_eq(y_tmp
, modulo_trunc
));
841 } else if (cell
->type
== ID($divfloor
)) {
842 if (cell
->parameters
[ID::A_SIGNED
].as_bool() && cell
->parameters
[ID::B_SIGNED
].as_bool())
843 ez
->assume(ez
->vec_eq(y_tmp
, ez
->vec_ite(
844 ez
->XOR(a
.back(), b
.back()),
845 ez
->vec_neg(ez
->vec_ite(
846 ez
->vec_reduce_or(modulo_trunc
),
847 ez
->vec_add(y_u
, ez
->vec_const_unsigned(1, y_u
.size())),
853 ez
->assume(ez
->vec_eq(y_tmp
, y_u
));
854 } else if (cell
->type
== ID($modfloor
)) {
855 ez
->assume(ez
->vec_eq(y_tmp
, ez
->vec_ite(floored_eq_trunc
, modulo_trunc
, ez
->vec_add(modulo_trunc
, b
))));
858 if (ignore_div_by_zero
) {
859 ez
->assume(ez
->expression(ezSAT::OpOr
, b
));
861 std::vector
<int> div_zero_result
;
862 if (cell
->type
.in(ID($div
), ID($divfloor
))) {
863 if (cell
->parameters
[ID::A_SIGNED
].as_bool() && cell
->parameters
[ID::B_SIGNED
].as_bool()) {
864 std::vector
<int> all_ones(y
.size(), ez
->CONST_TRUE
);
865 std::vector
<int> only_first_one(y
.size(), ez
->CONST_FALSE
);
866 only_first_one
.at(0) = ez
->CONST_TRUE
;
867 div_zero_result
= ez
->vec_ite(a
.back(), only_first_one
, all_ones
);
869 div_zero_result
.insert(div_zero_result
.end(), cell
->getPort(ID::A
).size(), ez
->CONST_TRUE
);
870 div_zero_result
.insert(div_zero_result
.end(), y
.size() - div_zero_result
.size(), ez
->CONST_FALSE
);
872 } else if (cell
->type
.in(ID($mod
), ID($modfloor
))) {
874 int copy_a_bits
= min(cell
->getPort(ID::A
).size(), cell
->getPort(ID::B
).size());
875 div_zero_result
.insert(div_zero_result
.end(), a
.begin(), a
.begin() + copy_a_bits
);
876 if (cell
->parameters
[ID::A_SIGNED
].as_bool() && cell
->parameters
[ID::B_SIGNED
].as_bool())
877 div_zero_result
.insert(div_zero_result
.end(), y
.size() - div_zero_result
.size(), div_zero_result
.back());
879 div_zero_result
.insert(div_zero_result
.end(), y
.size() - div_zero_result
.size(), ez
->CONST_FALSE
);
881 ez
->assume(ez
->vec_eq(yy
, ez
->vec_ite(ez
->expression(ezSAT::OpOr
, b
), y_tmp
, div_zero_result
)));
885 log_assert(arith_undef_handled
);
886 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
887 undefGating(y
, yy
, undef_y
);
892 if (cell
->type
== ID($lut
))
894 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
895 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
897 std::vector
<int> lut
;
898 for (auto bit
: cell
->getParam(ID::LUT
).bits
)
899 lut
.push_back(bit
== State::S1
? ez
->CONST_TRUE
: ez
->CONST_FALSE
);
900 while (GetSize(lut
) < (1 << GetSize(a
)))
901 lut
.push_back(ez
->CONST_FALSE
);
902 lut
.resize(1 << GetSize(a
));
906 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
907 std::vector
<int> t(lut
), u(GetSize(t
), ez
->CONST_FALSE
);
909 for (int i
= GetSize(a
)-1; i
>= 0; i
--)
911 std::vector
<int> t0(t
.begin(), t
.begin() + GetSize(t
)/2);
912 std::vector
<int> t1(t
.begin() + GetSize(t
)/2, t
.end());
914 std::vector
<int> u0(u
.begin(), u
.begin() + GetSize(u
)/2);
915 std::vector
<int> u1(u
.begin() + GetSize(u
)/2, u
.end());
917 t
= ez
->vec_ite(a
[i
], t1
, t0
);
918 u
= ez
->vec_ite(undef_a
[i
], ez
->vec_or(ez
->vec_xor(t0
, t1
), ez
->vec_or(u0
, u1
)), ez
->vec_ite(a
[i
], u1
, u0
));
921 log_assert(GetSize(t
) == 1);
922 log_assert(GetSize(u
) == 1);
923 undefGating(y
, t
, u
);
924 ez
->assume(ez
->vec_eq(importUndefSigSpec(cell
->getPort(ID::Y
), timestep
), u
));
928 std::vector
<int> t
= lut
;
929 for (int i
= GetSize(a
)-1; i
>= 0; i
--)
931 std::vector
<int> t0(t
.begin(), t
.begin() + GetSize(t
)/2);
932 std::vector
<int> t1(t
.begin() + GetSize(t
)/2, t
.end());
933 t
= ez
->vec_ite(a
[i
], t1
, t0
);
936 log_assert(GetSize(t
) == 1);
937 ez
->assume(ez
->vec_eq(y
, t
));
942 if (cell
->type
== ID($sop
))
944 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
945 int y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
).at(0);
947 int width
= cell
->getParam(ID::WIDTH
).as_int();
948 int depth
= cell
->getParam(ID::DEPTH
).as_int();
950 vector
<State
> table_raw
= cell
->getParam(ID::TABLE
).bits
;
951 while (GetSize(table_raw
) < 2*width
*depth
)
952 table_raw
.push_back(State::S0
);
954 vector
<vector
<int>> table(depth
);
956 for (int i
= 0; i
< depth
; i
++)
957 for (int j
= 0; j
< width
; j
++)
959 bool pat0
= (table_raw
[2*width
*i
+ 2*j
+ 0] == State::S1
);
960 bool pat1
= (table_raw
[2*width
*i
+ 2*j
+ 1] == State::S1
);
963 table
.at(i
).push_back(0);
964 else if (!pat0
&& pat1
)
965 table
.at(i
).push_back(1);
967 table
.at(i
).push_back(-1);
972 std::vector
<int> products
, undef_products
;
973 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
974 int undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
).at(0);
976 for (int i
= 0; i
< depth
; i
++)
978 std::vector
<int> cmp_a
, cmp_ua
, cmp_b
;
980 for (int j
= 0; j
< width
; j
++)
981 if (table
.at(i
).at(j
) >= 0) {
982 cmp_a
.push_back(a
.at(j
));
983 cmp_ua
.push_back(undef_a
.at(j
));
984 cmp_b
.push_back(table
.at(i
).at(j
) ? ez
->CONST_TRUE
: ez
->CONST_FALSE
);
987 std::vector
<int> masked_a
= ez
->vec_or(cmp_a
, cmp_ua
);
988 std::vector
<int> masked_b
= ez
->vec_or(cmp_b
, cmp_ua
);
990 int masked_eq
= ez
->vec_eq(masked_a
, masked_b
);
991 int any_undef
= ez
->expression(ezSAT::OpOr
, cmp_ua
);
993 undef_products
.push_back(ez
->AND(any_undef
, masked_eq
));
994 products
.push_back(ez
->AND(ez
->NOT(any_undef
), masked_eq
));
997 int yy
= ez
->expression(ezSAT::OpOr
, products
);
998 ez
->SET(undef_y
, ez
->AND(ez
->NOT(yy
), ez
->expression(ezSAT::OpOr
, undef_products
)));
999 undefGating(y
, yy
, undef_y
);
1003 std::vector
<int> products
;
1005 for (int i
= 0; i
< depth
; i
++)
1007 std::vector
<int> cmp_a
, cmp_b
;
1009 for (int j
= 0; j
< width
; j
++)
1010 if (table
.at(i
).at(j
) >= 0) {
1011 cmp_a
.push_back(a
.at(j
));
1012 cmp_b
.push_back(table
.at(i
).at(j
) ? ez
->CONST_TRUE
: ez
->CONST_FALSE
);
1015 products
.push_back(ez
->vec_eq(cmp_a
, cmp_b
));
1018 ez
->SET(y
, ez
->expression(ezSAT::OpOr
, products
));
1024 if (cell
->type
== ID($fa
))
1026 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
1027 std::vector
<int> b
= importDefSigSpec(cell
->getPort(ID::B
), timestep
);
1028 std::vector
<int> c
= importDefSigSpec(cell
->getPort(ID::C
), timestep
);
1029 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
1030 std::vector
<int> x
= importDefSigSpec(cell
->getPort(ID::X
), timestep
);
1032 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
1033 std::vector
<int> xx
= model_undef
? ez
->vec_var(x
.size()) : x
;
1035 std::vector
<int> t1
= ez
->vec_xor(a
, b
);
1036 ez
->assume(ez
->vec_eq(yy
, ez
->vec_xor(t1
, c
)));
1038 std::vector
<int> t2
= ez
->vec_and(a
, b
);
1039 std::vector
<int> t3
= ez
->vec_and(c
, t1
);
1040 ez
->assume(ez
->vec_eq(xx
, ez
->vec_or(t2
, t3
)));
1044 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
1045 std::vector
<int> undef_b
= importUndefSigSpec(cell
->getPort(ID::B
), timestep
);
1046 std::vector
<int> undef_c
= importUndefSigSpec(cell
->getPort(ID::C
), timestep
);
1048 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
1049 std::vector
<int> undef_x
= importUndefSigSpec(cell
->getPort(ID::X
), timestep
);
1051 ez
->assume(ez
->vec_eq(undef_y
, ez
->vec_or(ez
->vec_or(undef_a
, undef_b
), undef_c
)));
1052 ez
->assume(ez
->vec_eq(undef_x
, undef_y
));
1054 undefGating(y
, yy
, undef_y
);
1055 undefGating(x
, xx
, undef_x
);
1060 if (cell
->type
== ID($lcu
))
1062 std::vector
<int> p
= importDefSigSpec(cell
->getPort(ID::P
), timestep
);
1063 std::vector
<int> g
= importDefSigSpec(cell
->getPort(ID::G
), timestep
);
1064 std::vector
<int> ci
= importDefSigSpec(cell
->getPort(ID::CI
), timestep
);
1065 std::vector
<int> co
= importDefSigSpec(cell
->getPort(ID::CO
), timestep
);
1067 std::vector
<int> yy
= model_undef
? ez
->vec_var(co
.size()) : co
;
1069 for (int i
= 0; i
< GetSize(co
); i
++)
1070 ez
->SET(yy
[i
], ez
->OR(g
[i
], ez
->AND(p
[i
], i
? yy
[i
-1] : ci
[0])));
1074 std::vector
<int> undef_p
= importUndefSigSpec(cell
->getPort(ID::P
), timestep
);
1075 std::vector
<int> undef_g
= importUndefSigSpec(cell
->getPort(ID::G
), timestep
);
1076 std::vector
<int> undef_ci
= importUndefSigSpec(cell
->getPort(ID::CI
), timestep
);
1077 std::vector
<int> undef_co
= importUndefSigSpec(cell
->getPort(ID::CO
), timestep
);
1079 int undef_any_p
= ez
->expression(ezSAT::OpOr
, undef_p
);
1080 int undef_any_g
= ez
->expression(ezSAT::OpOr
, undef_g
);
1081 int undef_any_ci
= ez
->expression(ezSAT::OpOr
, undef_ci
);
1082 int undef_co_bit
= ez
->OR(undef_any_p
, undef_any_g
, undef_any_ci
);
1084 std::vector
<int> undef_co_bits(undef_co
.size(), undef_co_bit
);
1085 ez
->assume(ez
->vec_eq(undef_co_bits
, undef_co
));
1087 undefGating(co
, yy
, undef_co
);
1092 if (cell
->type
== ID($alu
))
1094 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
1095 std::vector
<int> b
= importDefSigSpec(cell
->getPort(ID::B
), timestep
);
1096 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
1097 std::vector
<int> x
= importDefSigSpec(cell
->getPort(ID::X
), timestep
);
1098 std::vector
<int> ci
= importDefSigSpec(cell
->getPort(ID::CI
), timestep
);
1099 std::vector
<int> bi
= importDefSigSpec(cell
->getPort(ID::BI
), timestep
);
1100 std::vector
<int> co
= importDefSigSpec(cell
->getPort(ID::CO
), timestep
);
1102 extendSignalWidth(a
, b
, y
, cell
);
1103 extendSignalWidth(a
, b
, x
, cell
);
1104 extendSignalWidth(a
, b
, co
, cell
);
1106 std::vector
<int> def_y
= model_undef
? ez
->vec_var(y
.size()) : y
;
1107 std::vector
<int> def_x
= model_undef
? ez
->vec_var(x
.size()) : x
;
1108 std::vector
<int> def_co
= model_undef
? ez
->vec_var(co
.size()) : co
;
1110 log_assert(GetSize(y
) == GetSize(x
));
1111 log_assert(GetSize(y
) == GetSize(co
));
1112 log_assert(GetSize(ci
) == 1);
1113 log_assert(GetSize(bi
) == 1);
1115 for (int i
= 0; i
< GetSize(y
); i
++)
1117 int s1
= a
.at(i
), s2
= ez
->XOR(b
.at(i
), bi
.at(0)), s3
= i
? co
.at(i
-1) : ci
.at(0);
1118 ez
->SET(def_x
.at(i
), ez
->XOR(s1
, s2
));
1119 ez
->SET(def_y
.at(i
), ez
->XOR(def_x
.at(i
), s3
));
1120 ez
->SET(def_co
.at(i
), ez
->OR(ez
->AND(s1
, s2
), ez
->AND(s1
, s3
), ez
->AND(s2
, s3
)));
1125 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
1126 std::vector
<int> undef_b
= importUndefSigSpec(cell
->getPort(ID::B
), timestep
);
1127 std::vector
<int> undef_ci
= importUndefSigSpec(cell
->getPort(ID::CI
), timestep
);
1128 std::vector
<int> undef_bi
= importUndefSigSpec(cell
->getPort(ID::BI
), timestep
);
1130 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
1131 std::vector
<int> undef_x
= importUndefSigSpec(cell
->getPort(ID::X
), timestep
);
1132 std::vector
<int> undef_co
= importUndefSigSpec(cell
->getPort(ID::CO
), timestep
);
1134 extendSignalWidth(undef_a
, undef_b
, undef_y
, cell
);
1135 extendSignalWidth(undef_a
, undef_b
, undef_x
, cell
);
1136 extendSignalWidth(undef_a
, undef_b
, undef_co
, cell
);
1138 std::vector
<int> all_inputs_undef
;
1139 all_inputs_undef
.insert(all_inputs_undef
.end(), undef_a
.begin(), undef_a
.end());
1140 all_inputs_undef
.insert(all_inputs_undef
.end(), undef_b
.begin(), undef_b
.end());
1141 all_inputs_undef
.insert(all_inputs_undef
.end(), undef_ci
.begin(), undef_ci
.end());
1142 all_inputs_undef
.insert(all_inputs_undef
.end(), undef_bi
.begin(), undef_bi
.end());
1143 int undef_any
= ez
->expression(ezSAT::OpOr
, all_inputs_undef
);
1145 for (int i
= 0; i
< GetSize(undef_y
); i
++) {
1146 ez
->SET(undef_y
.at(i
), undef_any
);
1147 ez
->SET(undef_x
.at(i
), ez
->OR(undef_a
.at(i
), undef_b
.at(i
), undef_bi
.at(0)));
1148 ez
->SET(undef_co
.at(i
), undef_any
);
1151 undefGating(y
, def_y
, undef_y
);
1152 undefGating(x
, def_x
, undef_x
);
1153 undefGating(co
, def_co
, undef_co
);
1158 if (cell
->type
== ID($slice
))
1160 RTLIL::SigSpec a
= cell
->getPort(ID::A
);
1161 RTLIL::SigSpec y
= cell
->getPort(ID::Y
);
1162 ez
->assume(signals_eq(a
.extract(cell
->parameters
.at(ID::OFFSET
).as_int(), y
.size()), y
, timestep
));
1166 if (cell
->type
== ID($concat
))
1168 RTLIL::SigSpec a
= cell
->getPort(ID::A
);
1169 RTLIL::SigSpec b
= cell
->getPort(ID::B
);
1170 RTLIL::SigSpec y
= cell
->getPort(ID::Y
);
1172 RTLIL::SigSpec ab
= a
;
1175 ez
->assume(signals_eq(ab
, y
, timestep
));
1179 if (timestep
> 0 && RTLIL::builtin_ff_cell_types().count(cell
->type
))
1181 FfData
ff(nullptr, cell
);
1183 // Latches and FFs with async inputs are not supported — use clk2fflogic or async2sync first.
1184 if (ff
.has_aload
|| ff
.has_arst
|| ff
.has_sr
)
1189 initial_state
.add((*sigmap
)(cell
->getPort(ID::Q
)));
1193 std::vector
<int> d
= importDefSigSpec(cell
->getPort(ID::D
), timestep
-1);
1194 std::vector
<int> undef_d
;
1196 undef_d
= importUndefSigSpec(cell
->getPort(ID::D
), timestep
-1);
1197 if (ff
.has_srst
&& ff
.has_ce
&& ff
.ce_over_srst
) {
1198 int srst
= importDefSigSpec(ff
.sig_srst
, timestep
-1).at(0);
1199 std::vector
<int> rval
= importDefSigSpec(ff
.val_srst
, timestep
-1);
1201 std::vector
<int> undef_rval
;
1203 undef_srst
= importUndefSigSpec(ff
.sig_srst
, timestep
-1).at(0);
1204 undef_rval
= importUndefSigSpec(ff
.val_srst
, timestep
-1);
1207 std::tie(d
, undef_d
) = mux(srst
, undef_srst
, d
, undef_d
, rval
, undef_rval
);
1209 std::tie(d
, undef_d
) = mux(srst
, undef_srst
, rval
, undef_rval
, d
, undef_d
);
1212 int ce
= importDefSigSpec(ff
.sig_ce
, timestep
-1).at(0);
1213 std::vector
<int> old_q
= importDefSigSpec(ff
.sig_q
, timestep
-1);
1215 std::vector
<int> undef_old_q
;
1217 undef_ce
= importUndefSigSpec(ff
.sig_ce
, timestep
-1).at(0);
1218 undef_old_q
= importUndefSigSpec(ff
.sig_q
, timestep
-1);
1221 std::tie(d
, undef_d
) = mux(ce
, undef_ce
, old_q
, undef_old_q
, d
, undef_d
);
1223 std::tie(d
, undef_d
) = mux(ce
, undef_ce
, d
, undef_d
, old_q
, undef_old_q
);
1225 if (ff
.has_srst
&& !(ff
.has_ce
&& ff
.ce_over_srst
)) {
1226 int srst
= importDefSigSpec(ff
.sig_srst
, timestep
-1).at(0);
1227 std::vector
<int> rval
= importDefSigSpec(ff
.val_srst
, timestep
-1);
1229 std::vector
<int> undef_rval
;
1231 undef_srst
= importUndefSigSpec(ff
.sig_srst
, timestep
-1).at(0);
1232 undef_rval
= importUndefSigSpec(ff
.val_srst
, timestep
-1);
1235 std::tie(d
, undef_d
) = mux(srst
, undef_srst
, d
, undef_d
, rval
, undef_rval
);
1237 std::tie(d
, undef_d
) = mux(srst
, undef_srst
, rval
, undef_rval
, d
, undef_d
);
1239 std::vector
<int> q
= importDefSigSpec(cell
->getPort(ID::Q
), timestep
);
1241 std::vector
<int> qq
= model_undef
? ez
->vec_var(q
.size()) : q
;
1242 ez
->assume(ez
->vec_eq(d
, qq
));
1246 std::vector
<int> undef_q
= importUndefSigSpec(cell
->getPort(ID::Q
), timestep
);
1248 ez
->assume(ez
->vec_eq(undef_d
, undef_q
));
1249 undefGating(q
, qq
, undef_q
);
1255 if (cell
->type
== ID($anyconst
))
1260 std::vector
<int> d
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
-1);
1261 std::vector
<int> q
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
1263 std::vector
<int> qq
= model_undef
? ez
->vec_var(q
.size()) : q
;
1264 ez
->assume(ez
->vec_eq(d
, qq
));
1268 std::vector
<int> undef_d
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
-1);
1269 std::vector
<int> undef_q
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
1271 ez
->assume(ez
->vec_eq(undef_d
, undef_q
));
1272 undefGating(q
, qq
, undef_q
);
1277 if (cell
->type
== ID($anyseq
))
1282 if (cell
->type
.in(ID($_BUF_
), ID($equiv
)))
1284 std::vector
<int> a
= importDefSigSpec(cell
->getPort(ID::A
), timestep
);
1285 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
1286 extendSignalWidthUnary(a
, y
, cell
);
1288 std::vector
<int> yy
= model_undef
? ez
->vec_var(y
.size()) : y
;
1289 ez
->assume(ez
->vec_eq(a
, yy
));
1292 std::vector
<int> undef_a
= importUndefSigSpec(cell
->getPort(ID::A
), timestep
);
1293 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
1294 extendSignalWidthUnary(undef_a
, undef_y
, cell
, false);
1295 ez
->assume(ez
->vec_eq(undef_a
, undef_y
));
1296 undefGating(y
, yy
, undef_y
);
1301 if (cell
->type
== ID($initstate
))
1303 auto key
= make_pair(prefix
, timestep
);
1304 if (initstates
.count(key
) == 0)
1305 initstates
[key
] = false;
1307 std::vector
<int> y
= importDefSigSpec(cell
->getPort(ID::Y
), timestep
);
1308 log_assert(GetSize(y
) == 1);
1309 ez
->SET(y
[0], initstates
[key
] ? ez
->CONST_TRUE
: ez
->CONST_FALSE
);
1312 std::vector
<int> undef_y
= importUndefSigSpec(cell
->getPort(ID::Y
), timestep
);
1313 log_assert(GetSize(undef_y
) == 1);
1314 ez
->SET(undef_y
[0], ez
->CONST_FALSE
);
1320 if (cell
->type
== ID($
assert))
1322 std::string pf
= prefix
+ (timestep
== -1 ? "" : stringf("@%d:", timestep
));
1323 asserts_a
[pf
].append((*sigmap
)(cell
->getPort(ID::A
)));
1324 asserts_en
[pf
].append((*sigmap
)(cell
->getPort(ID::EN
)));
1328 if (cell
->type
== ID($assume
))
1330 std::string pf
= prefix
+ (timestep
== -1 ? "" : stringf("@%d:", timestep
));
1331 assumes_a
[pf
].append((*sigmap
)(cell
->getPort(ID::A
)));
1332 assumes_en
[pf
].append((*sigmap
)(cell
->getPort(ID::EN
)));
1336 // Unsupported internal cell types: $pow $fsm $mem*
1337 // .. and all sequential cells with asynchronous inputs