Merge remote-tracking branch 'origin/eddie/shregmap_improve' into xc7mux
[yosys.git] / backends / aiger / aiger.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
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.
9 *
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.
17 *
18 */
19
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
22
23 USING_YOSYS_NAMESPACE
24 PRIVATE_NAMESPACE_BEGIN
25
26 void aiger_encode(std::ostream &f, int x)
27 {
28 log_assert(x >= 0);
29
30 while (x & ~0x7f) {
31 f.put((x & 0x7f) | 0x80);
32 x = x >> 7;
33 }
34
35 f.put(x);
36 }
37
38 struct AigerWriter
39 {
40 Module *module;
41 bool zinit_mode;
42 SigMap sigmap;
43
44 dict<SigBit, bool> init_map;
45 pool<SigBit> input_bits, output_bits;
46 dict<SigBit, SigBit> not_map, ff_map, alias_map;
47 dict<SigBit, pair<SigBit, SigBit>> and_map;
48 vector<pair<SigBit, SigBit>> asserts, assumes;
49 vector<pair<SigBit, SigBit>> liveness, fairness;
50 pool<SigBit> initstate_bits;
51
52 vector<pair<int, int>> aig_gates;
53 vector<int> aig_latchin, aig_latchinit, aig_outputs;
54 int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0;
55 int aig_b = 0, aig_c = 0, aig_j = 0, aig_f = 0;
56
57 dict<SigBit, int> aig_map;
58 dict<SigBit, int> ordered_outputs;
59 dict<SigBit, int> ordered_latches;
60
61 dict<SigBit, int> init_inputs;
62 int initstate_ff = 0;
63
64 int mkgate(int a0, int a1)
65 {
66 aig_m++, aig_a++;
67 aig_gates.push_back(a0 > a1 ? make_pair(a0, a1) : make_pair(a1, a0));
68 return 2*aig_m;
69 }
70
71 int bit2aig(SigBit bit)
72 {
73 if (aig_map.count(bit) == 0)
74 {
75 aig_map[bit] = -1;
76
77 if (initstate_bits.count(bit)) {
78 log_assert(initstate_ff > 0);
79 aig_map[bit] = initstate_ff;
80 } else
81 if (not_map.count(bit)) {
82 int a = bit2aig(not_map.at(bit)) ^ 1;
83 aig_map[bit] = a;
84 } else
85 if (and_map.count(bit)) {
86 auto args = and_map.at(bit);
87 int a0 = bit2aig(args.first);
88 int a1 = bit2aig(args.second);
89 aig_map[bit] = mkgate(a0, a1);
90 } else
91 if (alias_map.count(bit)) {
92 aig_map[bit] = bit2aig(alias_map.at(bit));
93 }
94
95 if (bit == State::Sx || bit == State::Sz)
96 log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n");
97 }
98
99 log_assert(aig_map.at(bit) >= 0);
100 return aig_map.at(bit);
101 }
102
103 AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module)
104 {
105 pool<SigBit> undriven_bits;
106 pool<SigBit> unused_bits;
107
108 // promote public wires
109 for (auto wire : module->wires())
110 if (wire->name[0] == '\\')
111 sigmap.add(wire);
112
113 // promote input wires
114 for (auto wire : module->wires())
115 if (wire->port_input)
116 sigmap.add(wire);
117
118 // promote output wires
119 for (auto wire : module->wires())
120 if (wire->port_output)
121 sigmap.add(wire);
122
123 for (auto wire : module->wires())
124 {
125 if (wire->attributes.count("\\init")) {
126 SigSpec initsig = sigmap(wire);
127 Const initval = wire->attributes.at("\\init");
128 for (int i = 0; i < GetSize(wire) && i < GetSize(initval); i++)
129 if (initval[i] == State::S0 || initval[i] == State::S1)
130 init_map[initsig[i]] = initval[i] == State::S1;
131 }
132
133 for (int i = 0; i < GetSize(wire); i++)
134 {
135 SigBit wirebit(wire, i);
136 SigBit bit = sigmap(wirebit);
137
138 if (bit.wire == nullptr) {
139 if (wire->port_output) {
140 aig_map[wirebit] = (bit == State::S1) ? 1 : 0;
141 output_bits.insert(wirebit);
142 }
143 continue;
144 }
145
146 undriven_bits.insert(bit);
147 unused_bits.insert(bit);
148
149 if (wire->port_input)
150 input_bits.insert(bit);
151
152 if (wire->port_output) {
153 if (bit != wirebit)
154 alias_map[wirebit] = bit;
155 output_bits.insert(wirebit);
156 }
157 }
158 }
159
160 for (auto bit : input_bits)
161 undriven_bits.erase(bit);
162
163 for (auto bit : output_bits)
164 unused_bits.erase(bit);
165
166 for (auto cell : module->cells())
167 {
168 if (cell->type == "$_NOT_")
169 {
170 SigBit A = sigmap(cell->getPort("\\A").as_bit());
171 SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
172 unused_bits.erase(A);
173 undriven_bits.erase(Y);
174 not_map[Y] = A;
175 continue;
176 }
177
178 if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_"))
179 {
180 SigBit D = sigmap(cell->getPort("\\D").as_bit());
181 SigBit Q = sigmap(cell->getPort("\\Q").as_bit());
182 unused_bits.erase(D);
183 undriven_bits.erase(Q);
184 ff_map[Q] = D;
185 continue;
186 }
187
188 if (cell->type == "$_AND_")
189 {
190 SigBit A = sigmap(cell->getPort("\\A").as_bit());
191 SigBit B = sigmap(cell->getPort("\\B").as_bit());
192 SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
193 unused_bits.erase(A);
194 unused_bits.erase(B);
195 undriven_bits.erase(Y);
196 and_map[Y] = make_pair(A, B);
197 continue;
198 }
199
200 if (cell->type == "$initstate")
201 {
202 SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
203 undriven_bits.erase(Y);
204 initstate_bits.insert(Y);
205 continue;
206 }
207
208 if (cell->type == "$assert")
209 {
210 SigBit A = sigmap(cell->getPort("\\A").as_bit());
211 SigBit EN = sigmap(cell->getPort("\\EN").as_bit());
212 unused_bits.erase(A);
213 unused_bits.erase(EN);
214 asserts.push_back(make_pair(A, EN));
215 continue;
216 }
217
218 if (cell->type == "$assume")
219 {
220 SigBit A = sigmap(cell->getPort("\\A").as_bit());
221 SigBit EN = sigmap(cell->getPort("\\EN").as_bit());
222 unused_bits.erase(A);
223 unused_bits.erase(EN);
224 assumes.push_back(make_pair(A, EN));
225 continue;
226 }
227
228 if (cell->type == "$live")
229 {
230 SigBit A = sigmap(cell->getPort("\\A").as_bit());
231 SigBit EN = sigmap(cell->getPort("\\EN").as_bit());
232 unused_bits.erase(A);
233 unused_bits.erase(EN);
234 liveness.push_back(make_pair(A, EN));
235 continue;
236 }
237
238 if (cell->type == "$fair")
239 {
240 SigBit A = sigmap(cell->getPort("\\A").as_bit());
241 SigBit EN = sigmap(cell->getPort("\\EN").as_bit());
242 unused_bits.erase(A);
243 unused_bits.erase(EN);
244 fairness.push_back(make_pair(A, EN));
245 continue;
246 }
247
248 if (cell->type == "$anyconst")
249 {
250 for (auto bit : sigmap(cell->getPort("\\Y"))) {
251 undriven_bits.erase(bit);
252 ff_map[bit] = bit;
253 }
254 continue;
255 }
256
257 if (cell->type == "$anyseq")
258 {
259 for (auto bit : sigmap(cell->getPort("\\Y"))) {
260 undriven_bits.erase(bit);
261 input_bits.insert(bit);
262 }
263 continue;
264 }
265
266 log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
267 }
268
269 for (auto bit : unused_bits)
270 undriven_bits.erase(bit);
271
272 if (!undriven_bits.empty()) {
273 undriven_bits.sort();
274 for (auto bit : undriven_bits) {
275 log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit));
276 input_bits.insert(bit);
277 }
278 log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module));
279 }
280
281 init_map.sort();
282 input_bits.sort();
283 output_bits.sort();
284 not_map.sort();
285 ff_map.sort();
286 and_map.sort();
287
288 aig_map[State::S0] = 0;
289 aig_map[State::S1] = 1;
290
291 for (auto bit : input_bits) {
292 aig_m++, aig_i++;
293 aig_map[bit] = 2*aig_m;
294 }
295
296 if (imode && input_bits.empty()) {
297 aig_m++, aig_i++;
298 }
299
300 if (zinit_mode)
301 {
302 for (auto it : ff_map) {
303 if (init_map.count(it.first))
304 continue;
305 aig_m++, aig_i++;
306 init_inputs[it.first] = 2*aig_m;
307 }
308 }
309
310 int fair_live_inputs_cnt = GetSize(liveness);
311 int fair_live_inputs_m = aig_m;
312
313 aig_m += fair_live_inputs_cnt;
314 aig_i += fair_live_inputs_cnt;
315
316 for (auto it : ff_map) {
317 aig_m++, aig_l++;
318 aig_map[it.first] = 2*aig_m;
319 ordered_latches[it.first] = aig_l-1;
320 if (init_map.count(it.first) == 0)
321 aig_latchinit.push_back(2);
322 else
323 aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0);
324 }
325
326 if (!initstate_bits.empty() || !init_inputs.empty()) {
327 aig_m++, aig_l++;
328 initstate_ff = 2*aig_m+1;
329 aig_latchinit.push_back(0);
330 }
331
332 int fair_live_latches_cnt = GetSize(fairness) + 2*GetSize(liveness);
333 int fair_live_latches_m = aig_m;
334 int fair_live_latches_l = aig_l;
335
336 aig_m += fair_live_latches_cnt;
337 aig_l += fair_live_latches_cnt;
338
339 for (int i = 0; i < fair_live_latches_cnt; i++)
340 aig_latchinit.push_back(0);
341
342 if (zinit_mode)
343 {
344 for (auto it : ff_map)
345 {
346 int l = ordered_latches[it.first];
347
348 if (aig_latchinit.at(l) == 1)
349 aig_map[it.first] ^= 1;
350
351 if (aig_latchinit.at(l) == 2)
352 {
353 int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1);
354 int gated_initin = mkgate(init_inputs[it.first], initstate_ff);
355 aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1;
356 }
357 }
358 }
359
360 for (auto it : ff_map) {
361 int a = bit2aig(it.second);
362 int l = ordered_latches[it.first];
363 if (zinit_mode && aig_latchinit.at(l) == 1)
364 aig_latchin.push_back(a ^ 1);
365 else
366 aig_latchin.push_back(a);
367 }
368
369 if (!initstate_bits.empty() || !init_inputs.empty())
370 aig_latchin.push_back(1);
371
372 for (auto bit : output_bits) {
373 aig_o++;
374 ordered_outputs[bit] = aig_o-1;
375 aig_outputs.push_back(bit2aig(bit));
376 }
377
378 if (omode && output_bits.empty()) {
379 aig_o++;
380 aig_outputs.push_back(0);
381 }
382
383 for (auto it : asserts) {
384 aig_b++;
385 int bit_a = bit2aig(it.first);
386 int bit_en = bit2aig(it.second);
387 aig_outputs.push_back(mkgate(bit_a^1, bit_en));
388 }
389
390 if (bmode && asserts.empty()) {
391 aig_b++;
392 aig_outputs.push_back(0);
393 }
394
395 for (auto it : assumes) {
396 aig_c++;
397 int bit_a = bit2aig(it.first);
398 int bit_en = bit2aig(it.second);
399 aig_outputs.push_back(mkgate(bit_a^1, bit_en)^1);
400 }
401
402 for (auto it : liveness)
403 {
404 int input_m = ++fair_live_inputs_m;
405 int latch_m1 = ++fair_live_latches_m;
406 int latch_m2 = ++fair_live_latches_m;
407
408 log_assert(GetSize(aig_latchin) == fair_live_latches_l);
409 fair_live_latches_l += 2;
410
411 int bit_a = bit2aig(it.first);
412 int bit_en = bit2aig(it.second);
413 int bit_s = 2*input_m;
414 int bit_q1 = 2*latch_m1;
415 int bit_q2 = 2*latch_m2;
416
417 int bit_d1 = mkgate(mkgate(bit_s, bit_en)^1, bit_q1^1)^1;
418 int bit_d2 = mkgate(mkgate(bit_d1, bit_a)^1, bit_q2^1)^1;
419
420 aig_j++;
421 aig_latchin.push_back(bit_d1);
422 aig_latchin.push_back(bit_d2);
423 aig_outputs.push_back(mkgate(bit_q1, bit_q2^1));
424 }
425
426 for (auto it : fairness)
427 {
428 int latch_m = ++fair_live_latches_m;
429
430 log_assert(GetSize(aig_latchin) == fair_live_latches_l);
431 fair_live_latches_l += 1;
432
433 int bit_a = bit2aig(it.first);
434 int bit_en = bit2aig(it.second);
435 int bit_q = 2*latch_m;
436
437 aig_f++;
438 aig_latchin.push_back(mkgate(mkgate(bit_q^1, bit_en^1)^1, bit_a^1));
439 aig_outputs.push_back(bit_q^1);
440 }
441 }
442
443 void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode)
444 {
445 int aig_obc = aig_o + aig_b + aig_c;
446 int aig_obcj = aig_obc + aig_j;
447 int aig_obcjf = aig_obcj + aig_f;
448
449 log_assert(aig_m == aig_i + aig_l + aig_a);
450 log_assert(aig_l == GetSize(aig_latchin));
451 log_assert(aig_l == GetSize(aig_latchinit));
452 log_assert(aig_obcjf == GetSize(aig_outputs));
453
454 if (miter_mode) {
455 if (aig_b || aig_c || aig_j || aig_f)
456 log_error("Running AIGER back-end in -miter mode, but design contains $assert, $assume, $live and/or $fair cells!\n");
457 f << stringf("%s %d %d %d 0 %d %d\n", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_a, aig_o);
458 } else {
459 f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a);
460 if (aig_b || aig_c || aig_j || aig_f)
461 f << stringf(" %d %d %d %d", aig_b, aig_c, aig_j, aig_f);
462 f << stringf("\n");
463 }
464
465 if (ascii_mode)
466 {
467 for (int i = 0; i < aig_i; i++)
468 f << stringf("%d\n", 2*i+2);
469
470 for (int i = 0; i < aig_l; i++) {
471 if (zinit_mode || aig_latchinit.at(i) == 0)
472 f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i));
473 else if (aig_latchinit.at(i) == 1)
474 f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i));
475 else if (aig_latchinit.at(i) == 2)
476 f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2);
477 }
478
479 for (int i = 0; i < aig_obc; i++)
480 f << stringf("%d\n", aig_outputs.at(i));
481
482 for (int i = aig_obc; i < aig_obcj; i++)
483 f << stringf("1\n");
484
485 for (int i = aig_obc; i < aig_obcj; i++)
486 f << stringf("%d\n", aig_outputs.at(i));
487
488 for (int i = aig_obcj; i < aig_obcjf; i++)
489 f << stringf("%d\n", aig_outputs.at(i));
490
491 for (int i = 0; i < aig_a; i++)
492 f << stringf("%d %d %d\n", 2*(aig_i+aig_l+i)+2, aig_gates.at(i).first, aig_gates.at(i).second);
493 }
494 else
495 {
496 for (int i = 0; i < aig_l; i++) {
497 if (zinit_mode || aig_latchinit.at(i) == 0)
498 f << stringf("%d\n", aig_latchin.at(i));
499 else if (aig_latchinit.at(i) == 1)
500 f << stringf("%d 1\n", aig_latchin.at(i));
501 else if (aig_latchinit.at(i) == 2)
502 f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2);
503 }
504
505 for (int i = 0; i < aig_obc; i++)
506 f << stringf("%d\n", aig_outputs.at(i));
507
508 for (int i = aig_obc; i < aig_obcj; i++)
509 f << stringf("1\n");
510
511 for (int i = aig_obc; i < aig_obcj; i++)
512 f << stringf("%d\n", aig_outputs.at(i));
513
514 for (int i = aig_obcj; i < aig_obcjf; i++)
515 f << stringf("%d\n", aig_outputs.at(i));
516
517 for (int i = 0; i < aig_a; i++) {
518 int lhs = 2*(aig_i+aig_l+i)+2;
519 int rhs0 = aig_gates.at(i).first;
520 int rhs1 = aig_gates.at(i).second;
521 int delta0 = lhs - rhs0;
522 int delta1 = rhs0 - rhs1;
523 aiger_encode(f, delta0);
524 aiger_encode(f, delta1);
525 }
526 }
527
528 if (symbols_mode)
529 {
530 dict<string, vector<string>> symbols;
531
532 for (auto wire : module->wires())
533 {
534 if (wire->name[0] == '$')
535 continue;
536
537 SigSpec sig = sigmap(wire);
538
539 for (int i = 0; i < GetSize(wire); i++)
540 {
541 if (sig[i].wire == nullptr) {
542 if (wire->port_output)
543 sig[i] = SigBit(wire, i);
544 else
545 continue;
546 }
547
548 if (wire->port_input) {
549 int a = aig_map.at(sig[i]);
550 log_assert((a & 1) == 0);
551 if (GetSize(wire) != 1)
552 symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i));
553 else
554 symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire)));
555 }
556
557 if (wire->port_output) {
558 int o = ordered_outputs.at(SigSpec(wire, i));
559 if (GetSize(wire) != 1)
560 symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i));
561 else
562 symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire)));
563 }
564
565 if (init_inputs.count(sig[i])) {
566 int a = init_inputs.at(sig[i]);
567 log_assert((a & 1) == 0);
568 if (GetSize(wire) != 1)
569 symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i));
570 else
571 symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire)));
572 }
573
574 if (ordered_latches.count(sig[i])) {
575 int l = ordered_latches.at(sig[i]);
576 const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : "";
577 if (GetSize(wire) != 1)
578 symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i));
579 else
580 symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire)));
581 }
582 }
583 }
584
585 symbols.sort();
586
587 for (auto &sym : symbols) {
588 f << sym.first;
589 std::sort(sym.second.begin(), sym.second.end());
590 for (auto &s : sym.second)
591 f << " " << s;
592 f << std::endl;
593 }
594 }
595
596 f << stringf("c\nGenerated by %s\n", yosys_version_str);
597 }
598
599 void write_map(std::ostream &f, bool verbose_map)
600 {
601 dict<int, string> input_lines;
602 dict<int, string> init_lines;
603 dict<int, string> output_lines;
604 dict<int, string> latch_lines;
605 dict<int, string> wire_lines;
606
607 for (auto wire : module->wires())
608 {
609 if (!verbose_map && wire->name[0] == '$')
610 continue;
611
612 SigSpec sig = sigmap(wire);
613
614 for (int i = 0; i < GetSize(wire); i++)
615 {
616 if (aig_map.count(sig[i]) == 0 || sig[i].wire == nullptr)
617 continue;
618
619 int a = aig_map.at(sig[i]);
620
621 if (verbose_map)
622 wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire));
623
624 if (wire->port_input) {
625 log_assert((a & 1) == 0);
626 input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire));
627 }
628
629 if (wire->port_output) {
630 int o = ordered_outputs.at(sig[i]);
631 output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire));
632 }
633
634 if (init_inputs.count(sig[i])) {
635 int a = init_inputs.at(sig[i]);
636 log_assert((a & 1) == 0);
637 init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire));
638 }
639
640 if (ordered_latches.count(sig[i])) {
641 int l = ordered_latches.at(sig[i]);
642 if (zinit_mode && (aig_latchinit.at(l) == 1))
643 latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire));
644 else
645 latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire));
646 }
647 }
648 }
649
650 input_lines.sort();
651 for (auto &it : input_lines)
652 f << it.second;
653
654 init_lines.sort();
655 for (auto &it : init_lines)
656 f << it.second;
657
658 output_lines.sort();
659 for (auto &it : output_lines)
660 f << it.second;
661
662 latch_lines.sort();
663 for (auto &it : latch_lines)
664 f << it.second;
665
666 wire_lines.sort();
667 for (auto &it : wire_lines)
668 f << it.second;
669 }
670 };
671
672 struct AigerBackend : public Backend {
673 AigerBackend() : Backend("aiger", "write design to AIGER file") { }
674 void help() YS_OVERRIDE
675 {
676 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
677 log("\n");
678 log(" write_aiger [options] [filename]\n");
679 log("\n");
680 log("Write the current design to an AIGER file. The design must be flattened and\n");
681 log("must not contain any cell types except $_AND_, $_NOT_, simple FF types,\n");
682 log("$assert and $assume cells, and $initstate cells.\n");
683 log("\n");
684 log("$assert and $assume cells are converted to AIGER bad state properties and\n");
685 log("invariant constraints.\n");
686 log("\n");
687 log(" -ascii\n");
688 log(" write ASCII version of AIGER format\n");
689 log("\n");
690 log(" -zinit\n");
691 log(" convert FFs to zero-initialized FFs, adding additional inputs for\n");
692 log(" uninitialized FFs.\n");
693 log("\n");
694 log(" -miter\n");
695 log(" design outputs are AIGER bad state properties\n");
696 log("\n");
697 log(" -symbols\n");
698 log(" include a symbol table in the generated AIGER file\n");
699 log("\n");
700 log(" -map <filename>\n");
701 log(" write an extra file with port and latch symbols\n");
702 log("\n");
703 log(" -vmap <filename>\n");
704 log(" like -map, but more verbose\n");
705 log("\n");
706 log(" -I, -O, -B\n");
707 log(" If the design contains no input/output/assert then create one\n");
708 log(" dummy input/output/bad_state pin to make the tools reading the\n");
709 log(" AIGER file happy.\n");
710 log("\n");
711 }
712 void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
713 {
714 bool ascii_mode = false;
715 bool zinit_mode = false;
716 bool miter_mode = false;
717 bool symbols_mode = false;
718 bool verbose_map = false;
719 bool imode = false;
720 bool omode = false;
721 bool bmode = false;
722 std::string map_filename;
723
724 log_header(design, "Executing AIGER backend.\n");
725
726 size_t argidx;
727 for (argidx = 1; argidx < args.size(); argidx++)
728 {
729 if (args[argidx] == "-ascii") {
730 ascii_mode = true;
731 continue;
732 }
733 if (args[argidx] == "-zinit") {
734 zinit_mode = true;
735 continue;
736 }
737 if (args[argidx] == "-miter") {
738 miter_mode = true;
739 continue;
740 }
741 if (args[argidx] == "-symbols") {
742 symbols_mode = true;
743 continue;
744 }
745 if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) {
746 map_filename = args[++argidx];
747 continue;
748 }
749 if (map_filename.empty() && args[argidx] == "-vmap" && argidx+1 < args.size()) {
750 map_filename = args[++argidx];
751 verbose_map = true;
752 continue;
753 }
754 if (args[argidx] == "-I") {
755 imode = true;
756 continue;
757 }
758 if (args[argidx] == "-O") {
759 omode = true;
760 continue;
761 }
762 if (args[argidx] == "-B") {
763 bmode = true;
764 continue;
765 }
766 break;
767 }
768 extra_args(f, filename, args, argidx);
769
770 Module *top_module = design->top_module();
771
772 if (top_module == nullptr)
773 log_error("Can't find top module in current design!\n");
774
775 AigerWriter writer(top_module, zinit_mode, imode, omode, bmode);
776 writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode);
777
778 if (!map_filename.empty()) {
779 std::ofstream mapf;
780 mapf.open(map_filename.c_str(), std::ofstream::trunc);
781 if (mapf.fail())
782 log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno));
783 writer.write_map(mapf, verbose_map);
784 }
785 }
786 } AigerBackend;
787
788 PRIVATE_NAMESPACE_END