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 #include "kernel/rtlil.h"
21 #include "kernel/register.h"
22 #include "kernel/sigtools.h"
23 #include "kernel/celltypes.h"
24 #include "kernel/log.h"
28 PRIVATE_NAMESPACE_BEGIN
34 RTLIL::Module
*module
;
38 int initstate_nid
= -1;
41 dict
<int, int> sorts_bv
;
43 // (<address-width>, <data-width>) => <sid>
44 dict
<pair
<int, int>, int> sorts_mem
;
46 // SigBit => (<nid>, <bitidx>)
47 dict
<SigBit
, pair
<int, int>> bit_nid
;
50 dict
<int, int> nid_width
;
53 dict
<SigSpec
, int> sig_nid
;
55 // bit to driving cell
56 dict
<SigBit
, Cell
*> bit_cell
;
59 dict
<Const
, int> consts
;
61 // ff inputs that need to be evaluated (<nid>, <ff_cell>)
62 vector
<pair
<int, Cell
*>> ff_todo
;
64 pool
<Cell
*> cell_recursion_guard
;
65 pool
<string
> output_symbols
;
68 void btorf(const char *fmt
, ...)
72 f
<< indent
<< vstringf(fmt
, ap
);
76 void btorf_push(const string
&id
)
79 f
<< indent
<< stringf(" ; begin %s\n", id
.c_str());
84 void btorf_pop(const string
&id
)
87 indent
= indent
.substr(4);
88 f
<< indent
<< stringf(" ; end %s\n", id
.c_str());
92 int get_bv_sid(int width
)
94 if (sorts_bv
.count(width
) == 0) {
96 btorf("%d sort bitvec %d\n", nid
, width
);
97 sorts_bv
[width
] = nid
;
99 return sorts_bv
.at(width
);
102 void add_nid_sig(int nid
, const SigSpec
&sig
)
104 for (int i
= 0; i
< GetSize(sig
); i
++)
105 bit_nid
[sig
[i
]] = make_pair(nid
, i
);
108 nid_width
[nid
] = GetSize(sig
);
111 void export_cell(Cell
*cell
)
113 log_assert(cell_recursion_guard
.count(cell
) == 0);
114 cell_recursion_guard
.insert(cell
);
115 btorf_push(log_id(cell
));
117 if (cell
->type
.in("$add", "$sub", "$and", "$or", "$xor", "$xnor", "$shl", "$sshl", "$shr", "$sshr", "$shift", "$shiftx",
118 "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_"))
121 if (cell
->type
== "$add") btor_op
= "add";
122 if (cell
->type
== "$sub") btor_op
= "sub";
123 if (cell
->type
.in("$shl", "$sshl")) btor_op
= "sll";
124 if (cell
->type
== "$shr") btor_op
= "srl";
125 if (cell
->type
== "$sshr") btor_op
= "sra";
126 if (cell
->type
.in("$shift", "$shiftx")) btor_op
= "shift";
127 if (cell
->type
.in("$and", "$_AND_")) btor_op
= "and";
128 if (cell
->type
.in("$or", "$_OR_")) btor_op
= "or";
129 if (cell
->type
.in("$xor", "$_XOR_")) btor_op
= "xor";
130 if (cell
->type
== "$_NAND_") btor_op
= "nand";
131 if (cell
->type
== "$_NOR_") btor_op
= "nor";
132 if (cell
->type
.in("$xnor", "$_XNOR_")) btor_op
= "xnor";
133 log_assert(!btor_op
.empty());
135 int width
= GetSize(cell
->getPort("\\Y"));
136 width
= std::max(width
, GetSize(cell
->getPort("\\A")));
137 width
= std::max(width
, GetSize(cell
->getPort("\\B")));
139 bool a_signed
= cell
->hasParam("\\A_SIGNED") ? cell
->getParam("\\A_SIGNED").as_bool() : false;
140 bool b_signed
= cell
->hasParam("\\B_SIGNED") ? cell
->getParam("\\B_SIGNED").as_bool() : false;
142 if (btor_op
== "shift" && !b_signed
)
145 if (cell
->type
.in("$shl", "$sshl", "$shr", "$sshr"))
148 if (cell
->type
== "$sshr" && !a_signed
)
151 int sid
= get_bv_sid(width
);
154 if (btor_op
== "shift")
156 int nid_a
= get_sig_nid(cell
->getPort("\\A"), width
, false);
157 int nid_b
= get_sig_nid(cell
->getPort("\\B"), width
, b_signed
);
159 int nid_r
= next_nid
++;
160 btorf("%d srl %d %d %d\n", nid_r
, sid
, nid_a
, nid_b
);
162 int nid_b_neg
= next_nid
++;
163 btorf("%d neg %d %d\n", nid_b_neg
, sid
, nid_b
);
165 int nid_l
= next_nid
++;
166 btorf("%d sll %d %d %d\n", nid_l
, sid
, nid_a
, nid_b_neg
);
168 int sid_bit
= get_bv_sid(1);
169 int nid_zero
= get_sig_nid(Const(0, width
));
170 int nid_b_ltz
= next_nid
++;
171 btorf("%d slt %d %d %d\n", nid_b_ltz
, sid_bit
, nid_b
, nid_zero
);
174 btorf("%d ite %d %d %d %d\n", nid
, sid
, nid_b_ltz
, nid_l
, nid_r
);
178 int nid_a
= get_sig_nid(cell
->getPort("\\A"), width
, a_signed
);
179 int nid_b
= get_sig_nid(cell
->getPort("\\B"), width
, b_signed
);
182 btorf("%d %s %d %d %d\n", nid
, btor_op
.c_str(), sid
, nid_a
, nid_b
);
185 SigSpec sig
= sigmap(cell
->getPort("\\Y"));
187 if (GetSize(sig
) < width
) {
188 int sid
= get_bv_sid(GetSize(sig
));
189 int nid2
= next_nid
++;
190 btorf("%d slice %d %d %d 0\n", nid2
, sid
, nid
, GetSize(sig
)-1);
194 add_nid_sig(nid
, sig
);
198 if (cell
->type
.in("$_ANDNOT_", "$_ORNOT_"))
200 int sid
= get_bv_sid(1);
201 int nid_a
= get_sig_nid(cell
->getPort("\\A"));
202 int nid_b
= get_sig_nid(cell
->getPort("\\B"));
204 int nid1
= next_nid
++;
205 int nid2
= next_nid
++;
207 if (cell
->type
== "$_ANDNOT_") {
208 btorf("%d not %d %d\n", nid1
, sid
, nid_b
);
209 btorf("%d and %d %d %d\n", nid2
, sid
, nid_a
, nid1
);
212 if (cell
->type
== "$_ORNOT_") {
213 btorf("%d not %d %d\n", nid1
, sid
, nid_b
);
214 btorf("%d or %d %d %d\n", nid2
, sid
, nid_a
, nid1
);
217 SigSpec sig
= sigmap(cell
->getPort("\\Y"));
218 add_nid_sig(nid2
, sig
);
222 if (cell
->type
.in("$_OAI3_", "$_AOI3_"))
224 int sid
= get_bv_sid(1);
225 int nid_a
= get_sig_nid(cell
->getPort("\\A"));
226 int nid_b
= get_sig_nid(cell
->getPort("\\B"));
227 int nid_c
= get_sig_nid(cell
->getPort("\\C"));
229 int nid1
= next_nid
++;
230 int nid2
= next_nid
++;
231 int nid3
= next_nid
++;
233 if (cell
->type
== "$_OAI3_") {
234 btorf("%d or %d %d %d\n", nid1
, sid
, nid_a
, nid_b
);
235 btorf("%d and %d %d %d\n", nid2
, sid
, nid1
, nid_c
);
236 btorf("%d not %d %d\n", nid3
, sid
, nid2
);
239 if (cell
->type
== "$_AOI3_") {
240 btorf("%d and %d %d %d\n", nid1
, sid
, nid_a
, nid_b
);
241 btorf("%d or %d %d %d\n", nid2
, sid
, nid1
, nid_c
);
242 btorf("%d not %d %d\n", nid3
, sid
, nid2
);
245 SigSpec sig
= sigmap(cell
->getPort("\\Y"));
246 add_nid_sig(nid3
, sig
);
250 if (cell
->type
.in("$_OAI4_", "$_AOI4_"))
252 int sid
= get_bv_sid(1);
253 int nid_a
= get_sig_nid(cell
->getPort("\\A"));
254 int nid_b
= get_sig_nid(cell
->getPort("\\B"));
255 int nid_c
= get_sig_nid(cell
->getPort("\\C"));
256 int nid_d
= get_sig_nid(cell
->getPort("\\D"));
258 int nid1
= next_nid
++;
259 int nid2
= next_nid
++;
260 int nid3
= next_nid
++;
261 int nid4
= next_nid
++;
263 if (cell
->type
== "$_OAI4_") {
264 btorf("%d or %d %d %d\n", nid1
, sid
, nid_a
, nid_b
);
265 btorf("%d or %d %d %d\n", nid2
, sid
, nid_c
, nid_d
);
266 btorf("%d and %d %d %d\n", nid3
, sid
, nid1
, nid2
);
267 btorf("%d not %d %d\n", nid4
, sid
, nid3
);
270 if (cell
->type
== "$_AOI4_") {
271 btorf("%d and %d %d %d\n", nid1
, sid
, nid_a
, nid_b
);
272 btorf("%d and %d %d %d\n", nid2
, sid
, nid_c
, nid_d
);
273 btorf("%d or %d %d %d\n", nid3
, sid
, nid1
, nid2
);
274 btorf("%d not %d %d\n", nid4
, sid
, nid3
);
277 SigSpec sig
= sigmap(cell
->getPort("\\Y"));
278 add_nid_sig(nid4
, sig
);
282 if (cell
->type
.in("$lt", "$le", "$eq", "$eqx", "$ne", "$nex", "$ge", "$gt"))
285 if (cell
->type
== "$lt") btor_op
= "lt";
286 if (cell
->type
== "$le") btor_op
= "lte";
287 if (cell
->type
.in("$eq", "$eqx")) btor_op
= "eq";
288 if (cell
->type
.in("$ne", "$nex")) btor_op
= "ne";
289 if (cell
->type
== "$ge") btor_op
= "gte";
290 if (cell
->type
== "$gt") btor_op
= "gt";
291 log_assert(!btor_op
.empty());
294 width
= std::max(width
, GetSize(cell
->getPort("\\A")));
295 width
= std::max(width
, GetSize(cell
->getPort("\\B")));
297 bool a_signed
= cell
->hasParam("\\A_SIGNED") ? cell
->getParam("\\A_SIGNED").as_bool() : false;
298 bool b_signed
= cell
->hasParam("\\B_SIGNED") ? cell
->getParam("\\B_SIGNED").as_bool() : false;
300 int sid
= get_bv_sid(1);
301 int nid_a
= get_sig_nid(cell
->getPort("\\A"), width
, a_signed
);
302 int nid_b
= get_sig_nid(cell
->getPort("\\B"), width
, b_signed
);
304 int nid
= next_nid
++;
305 if (cell
->type
.in("$lt", "$le", "$ge", "$gt")) {
306 btorf("%d %c%s %d %d %d\n", nid
, a_signed
|| b_signed
? 's' : 'u', btor_op
.c_str(), sid
, nid_a
, nid_b
);
308 btorf("%d %s %d %d %d\n", nid
, btor_op
.c_str(), sid
, nid_a
, nid_b
);
311 SigSpec sig
= sigmap(cell
->getPort("\\Y"));
313 if (GetSize(sig
) > 1) {
314 int sid
= get_bv_sid(GetSize(sig
));
315 int nid2
= next_nid
++;
316 btorf("%d uext %d %d %d\n", nid2
, sid
, nid
, GetSize(sig
) - 1);
320 add_nid_sig(nid
, sig
);
324 if (cell
->type
.in("$not", "$neg", "$_NOT_"))
327 if (cell
->type
.in("$not", "$_NOT_")) btor_op
= "not";
328 if (cell
->type
== "$neg") btor_op
= "neg";
329 log_assert(!btor_op
.empty());
331 int width
= GetSize(cell
->getPort("\\Y"));
332 width
= std::max(width
, GetSize(cell
->getPort("\\A")));
334 bool a_signed
= cell
->hasParam("\\A_SIGNED") ? cell
->getParam("\\A_SIGNED").as_bool() : false;
336 int sid
= get_bv_sid(width
);
337 int nid_a
= get_sig_nid(cell
->getPort("\\A"), width
, a_signed
);
339 int nid
= next_nid
++;
340 btorf("%d %s %d %d\n", nid
, btor_op
.c_str(), sid
, nid_a
);
342 SigSpec sig
= sigmap(cell
->getPort("\\Y"));
344 if (GetSize(sig
) < width
) {
345 int sid
= get_bv_sid(GetSize(sig
));
346 int nid2
= next_nid
++;
347 btorf("%d slice %d %d %d 0\n", nid2
, sid
, nid
, GetSize(sig
)-1);
351 add_nid_sig(nid
, sig
);
355 if (cell
->type
.in("$logic_and", "$logic_or", "$logic_not"))
358 if (cell
->type
== "$logic_and") btor_op
= "and";
359 if (cell
->type
== "$logic_or") btor_op
= "or";
360 if (cell
->type
== "$logic_not") btor_op
= "not";
361 log_assert(!btor_op
.empty());
363 int sid
= get_bv_sid(1);
364 int nid_a
= get_sig_nid(cell
->getPort("\\A"));
365 int nid_b
= btor_op
!= "not" ? get_sig_nid(cell
->getPort("\\B")) : 0;
367 if (GetSize(cell
->getPort("\\A")) > 1) {
368 int nid_red_a
= next_nid
++;
369 btorf("%d redor %d %d\n", nid_red_a
, sid
, nid_a
);
373 if (btor_op
!= "not" && GetSize(cell
->getPort("\\B")) > 1) {
374 int nid_red_b
= next_nid
++;
375 btorf("%d redor %d %d\n", nid_red_b
, sid
, nid_b
);
379 int nid
= next_nid
++;
380 if (btor_op
!= "not")
381 btorf("%d %s %d %d %d\n", nid
, btor_op
.c_str(), sid
, nid_a
, nid_b
);
383 btorf("%d %s %d %d\n", nid
, btor_op
.c_str(), sid
, nid_a
);
385 SigSpec sig
= sigmap(cell
->getPort("\\Y"));
387 if (GetSize(sig
) > 1) {
388 int sid
= get_bv_sid(GetSize(sig
));
389 int zeros_nid
= get_sig_nid(Const(0, GetSize(sig
)-1));
390 int nid2
= next_nid
++;
391 btorf("%d concat %d %d %d\n", nid2
, sid
, zeros_nid
, nid
);
395 add_nid_sig(nid
, sig
);
399 if (cell
->type
.in("$reduce_and", "$reduce_or", "$reduce_bool", "$reduce_xor", "$reduce_xnor"))
402 if (cell
->type
== "$reduce_and") btor_op
= "redand";
403 if (cell
->type
.in("$reduce_or", "$reduce_bool")) btor_op
= "redor";
404 if (cell
->type
.in("$reduce_xor", "$reduce_xnor")) btor_op
= "redxor";
405 log_assert(!btor_op
.empty());
407 int sid
= get_bv_sid(1);
408 int nid_a
= get_sig_nid(cell
->getPort("\\A"));
410 int nid
= next_nid
++;
411 btorf("%d %s %d %d\n", nid
, btor_op
.c_str(), sid
, nid_a
);
413 if (cell
->type
== "$reduce_xnor") {
414 int nid2
= next_nid
++;
415 btorf("%d not %d %d %d\n", nid2
, sid
, nid
);
419 SigSpec sig
= sigmap(cell
->getPort("\\Y"));
421 if (GetSize(sig
) > 1) {
422 int sid
= get_bv_sid(GetSize(sig
));
423 int zeros_nid
= get_sig_nid(Const(0, GetSize(sig
)-1));
424 int nid2
= next_nid
++;
425 btorf("%d concat %d %d %d\n", nid2
, sid
, zeros_nid
, nid
);
429 add_nid_sig(nid
, sig
);
433 if (cell
->type
.in("$mux", "$_MUX_"))
435 SigSpec sig_a
= sigmap(cell
->getPort("\\A"));
436 SigSpec sig_b
= sigmap(cell
->getPort("\\B"));
437 SigSpec sig_s
= sigmap(cell
->getPort("\\S"));
438 SigSpec sig_y
= sigmap(cell
->getPort("\\Y"));
440 int nid_a
= get_sig_nid(sig_a
);
441 int nid_b
= get_sig_nid(sig_b
);
442 int nid_s
= get_sig_nid(sig_s
);
444 int sid
= get_bv_sid(GetSize(sig_y
));
445 int nid
= next_nid
++;
446 btorf("%d ite %d %d %d %d\n", nid
, sid
, nid_s
, nid_b
, nid_a
);
448 add_nid_sig(nid
, sig_y
);
452 if (cell
->type
== "$pmux")
454 SigSpec sig_a
= sigmap(cell
->getPort("\\A"));
455 SigSpec sig_b
= sigmap(cell
->getPort("\\B"));
456 SigSpec sig_s
= sigmap(cell
->getPort("\\S"));
457 SigSpec sig_y
= sigmap(cell
->getPort("\\Y"));
459 int width
= GetSize(sig_a
);
460 int sid
= get_bv_sid(width
);
461 int nid
= get_sig_nid(sig_a
);
463 for (int i
= 0; i
< GetSize(sig_s
); i
++) {
464 int nid_b
= get_sig_nid(sig_b
.extract(i
*width
, width
));
465 int nid_s
= get_sig_nid(sig_s
.extract(i
));
466 int nid2
= next_nid
++;
467 btorf("%d ite %d %d %d %d\n", nid2
, sid
, nid_s
, nid_b
, nid
);
471 add_nid_sig(nid
, sig_y
);
475 if (cell
->type
.in("$dff", "$ff", "$_DFF_P_", "$_DFF_N", "$_FF_"))
477 SigSpec sig_d
= sigmap(cell
->getPort("\\D"));
478 SigSpec sig_q
= sigmap(cell
->getPort("\\Q"));
480 string symbol
= log_signal(sig_q
);
481 if (symbol
.find(' ') != string::npos
)
482 symbol
= log_id(cell
);
484 if (symbol
[0] == '\\')
485 symbol
= symbol
.substr(1);
487 int sid
= get_bv_sid(GetSize(sig_q
));
488 int nid
= next_nid
++;
490 if (output_symbols
.count(symbol
))
491 btorf("%d state %d\n", nid
, sid
);
493 btorf("%d state %d %s\n", nid
, sid
, symbol
.c_str());
495 ff_todo
.push_back(make_pair(nid
, cell
));
496 add_nid_sig(nid
, sig_q
);
500 if (cell
->type
== "$initstate")
502 SigSpec sig_y
= sigmap(cell
->getPort("\\Y"));
504 if (initstate_nid
< 0)
506 int sid
= get_bv_sid(1);
507 int one_nid
= get_sig_nid(Const(1, 1));
508 int zero_nid
= get_sig_nid(Const(0, 1));
509 initstate_nid
= next_nid
++;
510 btorf("%d state %d\n", initstate_nid
, sid
);
511 btorf("%d init %d %d %d\n", next_nid
++, sid
, initstate_nid
, one_nid
);
512 btorf("%d next %d %d %d\n", next_nid
++, sid
, initstate_nid
, zero_nid
);
515 add_nid_sig(initstate_nid
, sig_y
);
519 log_error("Unsupported cell type: %s (%s)\n", log_id(cell
->type
), log_id(cell
));
522 btorf_pop(log_id(cell
));
523 cell_recursion_guard
.erase(cell
);
526 int get_sig_nid(SigSpec sig
, int to_width
= -1, bool is_signed
= false)
530 if (sig_nid
.count(sig
) == 0)
533 vector
<pair
<int, int>> nidbits
;
536 for (int i
= 0; i
< GetSize(sig
); i
++)
540 if (bit_nid
.count(bit
) == 0)
542 if (bit
.wire
== nullptr)
546 while (i
+GetSize(c
) < GetSize(sig
) && sig
[i
+GetSize(c
)].wire
== nullptr)
547 c
.bits
.push_back(sig
[i
+GetSize(c
)].data
);
549 if (consts
.count(c
) == 0) {
550 int sid
= get_bv_sid(GetSize(c
));
551 int nid
= next_nid
++;
552 btorf("%d const %d %s\n", nid
, sid
, c
.as_string().c_str());
554 nid_width
[nid
] = GetSize(c
);
557 int nid
= consts
.at(c
);
559 for (int j
= 0; j
< GetSize(c
); j
++)
560 nidbits
.push_back(make_pair(nid
, j
));
567 export_cell(bit_cell
.at(bit
));
568 log_assert(bit_nid
.count(bit
));
572 nidbits
.push_back(bit_nid
.at(bit
));
578 // group bits and emit slice-concat chain
579 for (int i
= 0; i
< GetSize(nidbits
); i
++)
581 int nid2
= nidbits
[i
].first
;
582 int lower
= nidbits
[i
].second
;
585 while (i
+1 < GetSize(nidbits
) && nidbits
[i
+1].first
== nidbits
[i
].first
&&
586 nidbits
[i
+1].second
== nidbits
[i
].second
+1)
591 if (lower
!= 0 || upper
+1 != nid_width
.at(nid2
)) {
592 int sid
= get_bv_sid(upper
-lower
+1);
594 btorf("%d slice %d %d %d %d\n", nid3
, sid
, nid2
, upper
, lower
);
600 int sid
= get_bv_sid(width
+upper
-lower
+1);
602 btorf("%d concat %d %d %d\n", nid4
, sid
, nid3
, nid
);
605 width
+= upper
-lower
+1;
610 nid_width
[nid
] = width
;
613 int nid
= sig_nid
.at(sig
);
615 if (to_width
>= 0 && to_width
!= GetSize(sig
))
617 if (to_width
< GetSize(sig
))
619 int sid
= get_bv_sid(to_width
);
620 int nid2
= next_nid
++;
621 btorf("%d slice %d %d %d 0\n", nid2
, sid
, nid
, to_width
-1);
626 int sid
= get_bv_sid(to_width
);
627 int nid2
= next_nid
++;
628 btorf("%d %s %d %d %d\n", nid2
, is_signed
? "sext" : "uext",
629 sid
, nid
, to_width
- GetSize(sig
));
637 BtorWorker(std::ostream
&f
, RTLIL::Module
*module
, bool verbose
) :
638 f(f
), sigmap(module
), module(module
), verbose(verbose
)
640 btorf_push("inputs");
642 for (auto wire
: module
->wires())
644 if (!wire
->port_id
|| !wire
->port_input
)
647 SigSpec sig
= sigmap(wire
);
648 int sid
= get_bv_sid(GetSize(sig
));
649 int nid
= next_nid
++;
651 btorf("%d input %d %s\n", nid
, sid
, log_id(wire
));
652 add_nid_sig(nid
, sig
);
657 for (auto cell
: module
->cells())
658 for (auto &conn
: cell
->connections())
660 if (!cell
->output(conn
.first
))
663 for (auto bit
: sigmap(conn
.second
))
664 bit_cell
[bit
] = cell
;
667 for (auto wire
: module
->wires())
668 if (wire
->port_output
)
669 output_symbols
.insert(log_id(wire
));
671 for (auto wire
: module
->wires())
673 if (!wire
->port_id
|| !wire
->port_output
)
676 btorf_push(stringf("output %s", log_id(wire
)));
678 int sid
= get_bv_sid(GetSize(wire
));
679 int nid
= get_sig_nid(wire
);
680 btorf("%d output %d %d %s\n", next_nid
++, sid
, nid
, log_id(wire
));
682 btorf_pop(stringf("output %s", log_id(wire
)));
685 for (auto cell
: module
->cells())
687 if (cell
->type
== "$assume")
689 btorf_push(log_id(cell
));
691 int sid
= get_bv_sid(1);
692 int nid_a
= get_sig_nid(cell
->getPort("\\A"));
693 int nid_en
= get_sig_nid(cell
->getPort("\\EN"));
694 int nid_not_en
= next_nid
++;
695 int nid_a_or_not_en
= next_nid
++;
696 int nid
= next_nid
++;
698 btorf("%d not %d %d\n", nid_not_en
, sid
, nid_en
);
699 btorf("%d or %d %d %d\n", nid_a_or_not_en
, sid
, nid_a
, nid_not_en
);
700 btorf("%d constraint %d\n", nid
, nid_a_or_not_en
);
702 btorf_pop(log_id(cell
));
705 if (cell
->type
== "$assert")
707 btorf_push(log_id(cell
));
709 int sid
= get_bv_sid(1);
710 int nid_a
= get_sig_nid(cell
->getPort("\\A"));
711 int nid_en
= get_sig_nid(cell
->getPort("\\EN"));
712 int nid_not_a
= next_nid
++;
713 int nid_en_and_not_a
= next_nid
++;
714 int nid
= next_nid
++;
716 btorf("%d not %d %d\n", nid_not_a
, sid
, nid_a
);
717 btorf("%d and %d %d %d\n", nid_en_and_not_a
, sid
, nid_en
, nid_not_a
);
718 btorf("%d bad %d\n", nid
, nid_en_and_not_a
);
720 btorf_pop(log_id(cell
));
724 while (!ff_todo
.empty())
726 vector
<pair
<int, Cell
*>> todo
;
729 for (auto &it
: todo
)
731 btorf_push(stringf("next %s", log_id(it
.second
)));
733 SigSpec sig
= sigmap(it
.second
->getPort("\\D"));
735 int nid
= get_sig_nid(sig
);
736 int sid
= get_bv_sid(GetSize(sig
));
737 btorf("%d next %d %d %d\n", next_nid
++, sid
, it
.first
, nid
);
739 btorf_pop(stringf("next %s", log_id(it
.second
)));
745 struct BtorBackend
: public Backend
{
746 BtorBackend() : Backend("btor", "write design to BTOR file") { }
749 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
751 log(" write_btor [options] [filename]\n");
753 log("Write a BTOR description of the current design.\n");
756 log(" Add comments and indentation to BTOR output file\n");
759 virtual void execute(std::ostream
*&f
, std::string filename
, std::vector
<std::string
> args
, RTLIL::Design
*design
)
761 bool verbose
= false;
763 log_header(design
, "Executing BTOR backend.\n");
766 for (argidx
= 1; argidx
< args
.size(); argidx
++)
768 if (args
[argidx
] == "-v") {
774 extra_args(f
, filename
, args
, argidx
);
776 RTLIL::Module
*topmod
= design
->top_module();
778 if (topmod
== nullptr)
779 log_cmd_error("No top module found.\n");
781 *f
<< stringf("; BTOR description generated by %s for module %s.\n",
782 yosys_version_str
, log_id(topmod
));
784 BtorWorker(*f
, topmod
, verbose
);
786 *f
<< stringf("; end of yosys output\n");
790 PRIVATE_NAMESPACE_END