2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * Copyright (C) 2019 Eddie Hung <eddie@fpgeh.com>
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 // [[CITE]] The AIGER And-Inverter Graph (AIG) Format Version 20071012
22 // Armin Biere. The AIGER And-Inverter Graph (AIG) Format Version 20071012. Technical Report 07/1, October 2011, FMV Reports Series, Institute for Formal Models and Verification, Johannes Kepler University, Altenbergerstr. 69, 4040 Linz, Austria.
23 // http://fmv.jku.at/papers/Biere-FMV-TR-07-1.pdf
31 #include "kernel/yosys.h"
32 #include "kernel/sigtools.h"
33 #include "kernel/consteval.h"
34 #include "aigerparse.h"
38 AigerReader::AigerReader(RTLIL::Design
*design
, std::istream
&f
, RTLIL::IdString module_name
, RTLIL::IdString clk_name
, std::string map_filename
, bool wideports
)
39 : design(design
), f(f
), clk_name(clk_name
), map_filename(map_filename
), wideports(wideports
)
41 module
= new RTLIL::Module
;
42 module
->name
= module_name
;
43 if (design
->module(module
->name
))
44 log_error("Duplicate definition of module %s!\n", log_id(module
->name
));
47 void AigerReader::parse_aiger()
51 if (header
!= "aag" && header
!= "aig")
52 log_error("Unsupported AIGER file!\n");
54 // Parse rest of header
55 if (!(f
>> M
>> I
>> L
>> O
>> A
))
56 log_error("Invalid AIGER header\n");
60 if (f
.peek() != ' ') goto end_of_header
;
61 if (!(f
>> B
)) log_error("Invalid AIGER header\n");
62 if (f
.peek() != ' ') goto end_of_header
;
63 if (!(f
>> C
)) log_error("Invalid AIGER header\n");
64 if (f
.peek() != ' ') goto end_of_header
;
65 if (!(f
>> J
)) log_error("Invalid AIGER header\n");
66 if (f
.peek() != ' ') goto end_of_header
;
67 if (!(f
>> F
)) log_error("Invalid AIGER header\n");
71 std::getline(f
, line
); // Ignore up to start of next line, as standard
72 // says anything that follows could be used for
75 log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M
, I
, L
, O
, A
, B
, C
, J
, F
);
83 else if (header
== "aig")
88 RTLIL::Wire
* n0
= module
->wire("\\__0__");
90 module
->connect(n0
, RTLIL::S0
);
92 // Parse footer (symbol table, comments, etc.)
95 for (int c
= f
.peek(); c
!= EOF
; c
= f
.peek(), ++line_count
) {
96 if (c
== 'i' || c
== 'l' || c
== 'o' || c
== 'b') {
99 log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count
);
101 if ((c
== 'i' && l1
> inputs
.size()) || (c
== 'l' && l1
> latches
.size()) || (c
== 'o' && l1
> outputs
.size()))
102 log_error("Line %u has invalid symbol position!\n", line_count
);
105 if (c
== 'i') wire
= inputs
[l1
];
106 else if (c
== 'l') wire
= latches
[l1
];
107 else if (c
== 'o') wire
= outputs
[l1
];
108 else if (c
== 'b') wire
= bad_properties
[l1
];
111 module
->rename(wire
, stringf("\\%s", s
.c_str()));
113 else if (c
== 'j' || c
== 'f') {
118 if (f
.peek() == '\n')
120 // Else constraint (TODO)
123 log_error("Line %u: cannot interpret first character '%c'!\n", line_count
, c
);
124 std::getline(f
, line
); // Ignore up to start of next line
130 static uint32_t parse_xaiger_literal(std::istream
&f
)
133 f
.read(reinterpret_cast<char*>(&l
), sizeof(l
));
134 if (f
.gcount() != sizeof(l
))
135 log_error("Offset %ld: unable to read literal!\n", static_cast<int64_t>(f
.tellg()));
136 // TODO: Don't assume we're on little endian
138 return _byteswap_ulong(l
);
140 return __builtin_bswap32(l
);
144 static RTLIL::Wire
* createWireIfNotExists(RTLIL::Module
*module
, unsigned literal
)
146 const unsigned variable
= literal
>> 1;
147 const bool invert
= literal
& 1;
148 RTLIL::IdString
wire_name(stringf("\\__%d%s__", variable
, invert
? "b" : "")); // FIXME: is "b" the right suffix?
149 RTLIL::Wire
*wire
= module
->wire(wire_name
);
150 if (wire
) return wire
;
151 log_debug("Creating %s\n", wire_name
.c_str());
152 wire
= module
->addWire(wire_name
);
153 wire
->port_input
= wire
->port_output
= false;
154 if (!invert
) return wire
;
155 RTLIL::IdString
wire_inv_name(stringf("\\__%d__", variable
));
156 RTLIL::Wire
*wire_inv
= module
->wire(wire_inv_name
);
158 if (module
->cell(wire_inv_name
)) return wire
;
161 log_debug("Creating %s\n", wire_inv_name
.c_str());
162 wire_inv
= module
->addWire(wire_inv_name
);
163 wire_inv
->port_input
= wire_inv
->port_output
= false;
166 log_debug("Creating %s = ~%s\n", wire_name
.c_str(), wire_inv_name
.c_str());
167 module
->addNotGate(stringf("\\__%d__$not", variable
), wire_inv
, wire
); // FIXME: is "$not" the right suffix?
172 void AigerReader::parse_xaiger()
176 if (header
!= "aag" && header
!= "aig")
177 log_error("Unsupported AIGER file!\n");
179 // Parse rest of header
180 if (!(f
>> M
>> I
>> L
>> O
>> A
))
181 log_error("Invalid AIGER header\n");
187 std::getline(f
, line
); // Ignore up to start of next line, as standard
188 // says anything that follows could be used for
191 log_debug("M=%u I=%u L=%u O=%u A=%u\n", M
, I
, L
, O
, A
);
199 else if (header
== "aig")
200 parse_aiger_binary();
204 RTLIL::Wire
* n0
= module
->wire("\\__0__");
206 module
->connect(n0
, RTLIL::S0
);
208 dict
<int,IdString
> box_lookup
;
209 for (auto m
: design
->modules()) {
210 auto it
= m
->attributes
.find("\\abc_box_id");
211 if (it
== m
->attributes
.end())
213 if (m
->name
[0] == '$') continue;
214 auto r
= box_lookup
.insert(std::make_pair(it
->second
.as_int(), m
->name
));
215 log_assert(r
.second
);
218 // Parse footer (symbol table, comments, etc.)
220 bool comment_seen
= false;
221 for (int c
= f
.peek(); c
!= EOF
; c
= f
.peek()) {
222 if (comment_seen
|| c
== 'c') {
233 uint32_t dataSize
= parse_xaiger_literal(f
);
234 uint32_t lutNum
= parse_xaiger_literal(f
);
235 uint32_t lutSize
= parse_xaiger_literal(f
);
236 log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize
, lutNum
, lutSize
);
237 ConstEval
ce(module
);
238 for (unsigned i
= 0; i
< lutNum
; ++i
) {
239 uint32_t rootNodeID
= parse_xaiger_literal(f
);
240 uint32_t cutLeavesM
= parse_xaiger_literal(f
);
241 log_debug("rootNodeID=%d cutLeavesM=%d\n", rootNodeID
, cutLeavesM
);
242 RTLIL::Wire
*output_sig
= module
->wire(stringf("\\__%d__", rootNodeID
));
244 RTLIL::SigSpec input_sig
;
245 for (unsigned j
= 0; j
< cutLeavesM
; ++j
) {
246 nodeID
= parse_xaiger_literal(f
);
247 log_debug("\t%u\n", nodeID
);
248 RTLIL::Wire
*wire
= module
->wire(stringf("\\__%d__", nodeID
));
250 input_sig
.append(wire
);
252 RTLIL::Const
lut_mask(RTLIL::State::Sx
, 1 << input_sig
.size());
253 for (int j
= 0; j
< (1 << cutLeavesM
); ++j
) {
255 ce
.set(input_sig
, RTLIL::Const
{j
, static_cast<int>(cutLeavesM
)});
256 RTLIL::SigSpec
o(output_sig
);
258 lut_mask
[j
] = o
.as_const()[0];
261 RTLIL::Cell
*output_cell
= module
->cell(stringf("\\__%d__$and", rootNodeID
));
262 log_assert(output_cell
);
263 module
->remove(output_cell
);
264 module
->addLut(stringf("\\__%d__$lut", rootNodeID
), input_sig
, output_sig
, std::move(lut_mask
));
268 uint32_t dataSize
= parse_xaiger_literal(f
);
269 flopNum
= parse_xaiger_literal(f
);
270 log_assert(dataSize
== (flopNum
+1) * sizeof(uint32_t));
271 f
.ignore(flopNum
* sizeof(uint32_t));
274 parse_xaiger_literal(f
);
276 log_debug("n: '%s'\n", s
.c_str());
279 f
.ignore(sizeof(uint32_t));
280 uint32_t version
= parse_xaiger_literal(f
);
281 log_assert(version
== 1);
282 uint32_t ciNum
= parse_xaiger_literal(f
);
283 log_debug("ciNum = %u\n", ciNum
);
284 uint32_t coNum
= parse_xaiger_literal(f
);
285 log_debug("coNum = %u\n", coNum
);
286 piNum
= parse_xaiger_literal(f
);
287 log_debug("piNum = %u\n", piNum
);
288 uint32_t poNum
= parse_xaiger_literal(f
);
289 log_debug("poNum = %u\n", poNum
);
290 uint32_t boxNum
= parse_xaiger_literal(f
);
291 log_debug("boxNum = %u\n", poNum
);
292 for (unsigned i
= 0; i
< boxNum
; i
++) {
293 f
.ignore(2*sizeof(uint32_t));
294 uint32_t boxUniqueId
= parse_xaiger_literal(f
);
295 log_assert(boxUniqueId
> 0);
296 uint32_t oldBoxNum
= parse_xaiger_literal(f
);
297 RTLIL::Cell
* cell
= module
->addCell(stringf("$__box%u__", oldBoxNum
), box_lookup
.at(boxUniqueId
));
298 boxes
.emplace_back(cell
);
301 else if (c
== 'a' || c
== 'i' || c
== 'o') {
302 uint32_t dataSize
= parse_xaiger_literal(f
);
310 log_error("Line %u: cannot interpret first character '%c'!\n", line_count
, c
);
316 void AigerReader::parse_aiger_ascii()
319 std::stringstream ss
;
324 for (unsigned i
= 1; i
<= I
; ++i
, ++line_count
) {
326 log_error("Line %u cannot be interpreted as an input!\n", line_count
);
327 log_debug("%d is an input\n", l1
);
328 log_assert(!(l1
& 1)); // Inputs can't be inverted
329 RTLIL::Wire
*wire
= createWireIfNotExists(module
, l1
);
330 wire
->port_input
= true;
331 inputs
.push_back(wire
);
335 RTLIL::Wire
*clk_wire
= nullptr;
337 log_assert(clk_name
!= "");
338 clk_wire
= module
->wire(clk_name
);
339 log_assert(!clk_wire
);
340 log_debug("Creating %s\n", clk_name
.c_str());
341 clk_wire
= module
->addWire(clk_name
);
342 clk_wire
->port_input
= true;
343 clk_wire
->port_output
= false;
345 for (unsigned i
= 0; i
< L
; ++i
, ++line_count
) {
346 if (!(f
>> l1
>> l2
))
347 log_error("Line %u cannot be interpreted as a latch!\n", line_count
);
348 log_debug("%d %d is a latch\n", l1
, l2
);
349 log_assert(!(l1
& 1)); // TODO: Latch outputs can't be inverted?
350 RTLIL::Wire
*q_wire
= createWireIfNotExists(module
, l1
);
351 RTLIL::Wire
*d_wire
= createWireIfNotExists(module
, l2
);
353 module
->addDffGate(NEW_ID
, clk_wire
, d_wire
, q_wire
);
355 // Reset logic is optional in AIGER 1.9
356 if (f
.peek() == ' ') {
358 log_error("Line %u cannot be interpreted as a latch!\n", line_count
);
361 q_wire
->attributes
["\\init"] = RTLIL::S0
;
363 q_wire
->attributes
["\\init"] = RTLIL::S1
;
365 //q_wire->attributes["\\init"] = RTLIL::Sx;
368 log_error("Line %u has invalid reset literal for latch!\n", line_count
);
371 // AIGER latches are assumed to be initialized to zero
372 q_wire
->attributes
["\\init"] = RTLIL::S0
;
374 latches
.push_back(q_wire
);
378 for (unsigned i
= 0; i
< O
; ++i
, ++line_count
) {
380 log_error("Line %u cannot be interpreted as an output!\n", line_count
);
382 log_debug("%d is an output\n", l1
);
383 const unsigned variable
= l1
>> 1;
384 const bool invert
= l1
& 1;
385 RTLIL::IdString
wire_name(stringf("\\__%d%s__", variable
, invert
? "b" : "")); // FIXME: is "b" the right suffix?
386 RTLIL::Wire
*wire
= module
->wire(wire_name
);
388 wire
= createWireIfNotExists(module
, l1
);
389 else if (wire
->port_input
|| wire
->port_output
) {
390 RTLIL::Wire
*new_wire
= module
->addWire(NEW_ID
);
391 module
->connect(new_wire
, wire
);
394 wire
->port_output
= true;
395 outputs
.push_back(wire
);
398 // Parse bad properties
399 for (unsigned i
= 0; i
< B
; ++i
, ++line_count
) {
401 log_error("Line %u cannot be interpreted as a bad state property!\n", line_count
);
403 log_debug("%d is a bad state property\n", l1
);
404 RTLIL::Wire
*wire
= createWireIfNotExists(module
, l1
);
405 wire
->port_output
= true;
406 bad_properties
.push_back(wire
);
409 // TODO: Parse invariant constraints
410 for (unsigned i
= 0; i
< C
; ++i
, ++line_count
)
411 std::getline(f
, line
); // Ignore up to start of next line
413 // TODO: Parse justice properties
414 for (unsigned i
= 0; i
< J
; ++i
, ++line_count
)
415 std::getline(f
, line
); // Ignore up to start of next line
417 // TODO: Parse fairness constraints
418 for (unsigned i
= 0; i
< F
; ++i
, ++line_count
)
419 std::getline(f
, line
); // Ignore up to start of next line
422 for (unsigned i
= 0; i
< A
; ++i
) {
423 if (!(f
>> l1
>> l2
>> l3
))
424 log_error("Line %u cannot be interpreted as an AND!\n", line_count
);
426 log_debug("%d %d %d is an AND\n", l1
, l2
, l3
);
427 log_assert(!(l1
& 1));
428 RTLIL::Wire
*o_wire
= createWireIfNotExists(module
, l1
);
429 RTLIL::Wire
*i1_wire
= createWireIfNotExists(module
, l2
);
430 RTLIL::Wire
*i2_wire
= createWireIfNotExists(module
, l3
);
431 module
->addAndGate(o_wire
->name
.str() + "$and", i1_wire
, i2_wire
, o_wire
);
433 std::getline(f
, line
); // Ignore up to start of next line
436 static unsigned parse_next_delta_literal(std::istream
&f
, unsigned ref
)
438 unsigned x
= 0, i
= 0;
440 while ((ch
= f
.get()) & 0x80)
441 x
|= (ch
& 0x7f) << (7 * i
++);
442 return ref
- (x
| (ch
<< (7 * i
)));
445 void AigerReader::parse_aiger_binary()
451 for (unsigned i
= 1; i
<= I
; ++i
) {
452 log_debug("%d is an input\n", i
);
453 RTLIL::Wire
*wire
= createWireIfNotExists(module
, i
<< 1);
454 wire
->port_input
= true;
455 log_assert(!wire
->port_output
);
456 inputs
.push_back(wire
);
460 RTLIL::Wire
*clk_wire
= nullptr;
462 log_assert(clk_name
!= "");
463 clk_wire
= module
->wire(clk_name
);
464 log_assert(!clk_wire
);
465 log_debug("Creating %s\n", clk_name
.c_str());
466 clk_wire
= module
->addWire(clk_name
);
467 clk_wire
->port_input
= true;
468 clk_wire
->port_output
= false;
471 for (unsigned i
= 0; i
< L
; ++i
, ++line_count
, l1
+= 2) {
473 log_error("Line %u cannot be interpreted as a latch!\n", line_count
);
474 log_debug("%d %d is a latch\n", l1
, l2
);
475 RTLIL::Wire
*q_wire
= createWireIfNotExists(module
, l1
);
476 RTLIL::Wire
*d_wire
= createWireIfNotExists(module
, l2
);
478 module
->addDff(NEW_ID
, clk_wire
, d_wire
, q_wire
);
480 // Reset logic is optional in AIGER 1.9
481 if (f
.peek() == ' ') {
483 log_error("Line %u cannot be interpreted as a latch!\n", line_count
);
486 q_wire
->attributes
["\\init"] = RTLIL::S0
;
488 q_wire
->attributes
["\\init"] = RTLIL::S1
;
490 //q_wire->attributes["\\init"] = RTLIL::Sx;
493 log_error("Line %u has invalid reset literal for latch!\n", line_count
);
496 // AIGER latches are assumed to be initialized to zero
497 q_wire
->attributes
["\\init"] = RTLIL::S0
;
499 latches
.push_back(q_wire
);
503 for (unsigned i
= 0; i
< O
; ++i
, ++line_count
) {
505 log_error("Line %u cannot be interpreted as an output!\n", line_count
);
507 log_debug("%d is an output\n", l1
);
508 const unsigned variable
= l1
>> 1;
509 const bool invert
= l1
& 1;
510 RTLIL::IdString
wire_name(stringf("\\__%d%s__", variable
, invert
? "b" : "")); // FIXME: is "_b" the right suffix?
511 RTLIL::Wire
*wire
= module
->wire(wire_name
);
513 wire
= createWireIfNotExists(module
, l1
);
514 else if (wire
->port_input
|| wire
->port_output
) {
515 RTLIL::Wire
*new_wire
= module
->addWire(NEW_ID
);
516 module
->connect(new_wire
, wire
);
519 wire
->port_output
= true;
520 outputs
.push_back(wire
);
522 std::getline(f
, line
); // Ignore up to start of next line
524 // Parse bad properties
525 for (unsigned i
= 0; i
< B
; ++i
, ++line_count
) {
527 log_error("Line %u cannot be interpreted as a bad state property!\n", line_count
);
529 log_debug("%d is a bad state property\n", l1
);
530 RTLIL::Wire
*wire
= createWireIfNotExists(module
, l1
);
531 wire
->port_output
= true;
532 bad_properties
.push_back(wire
);
535 std::getline(f
, line
); // Ignore up to start of next line
537 // TODO: Parse invariant constraints
538 for (unsigned i
= 0; i
< C
; ++i
, ++line_count
)
539 std::getline(f
, line
); // Ignore up to start of next line
541 // TODO: Parse justice properties
542 for (unsigned i
= 0; i
< J
; ++i
, ++line_count
)
543 std::getline(f
, line
); // Ignore up to start of next line
545 // TODO: Parse fairness constraints
546 for (unsigned i
= 0; i
< F
; ++i
, ++line_count
)
547 std::getline(f
, line
); // Ignore up to start of next line
551 for (unsigned i
= 0; i
< A
; ++i
, ++line_count
, l1
+= 2) {
552 l2
= parse_next_delta_literal(f
, l1
);
553 l3
= parse_next_delta_literal(f
, l2
);
555 log_debug("%d %d %d is an AND\n", l1
, l2
, l3
);
556 log_assert(!(l1
& 1));
557 RTLIL::Wire
*o_wire
= createWireIfNotExists(module
, l1
);
558 RTLIL::Wire
*i1_wire
= createWireIfNotExists(module
, l2
);
559 RTLIL::Wire
*i2_wire
= createWireIfNotExists(module
, l3
);
560 module
->addAndGate(o_wire
->name
.str() + "$and", i1_wire
, i2_wire
, o_wire
);
564 void AigerReader::post_process()
566 pool
<RTLIL::Module
*> abc_carry_modules
;
567 unsigned ci_count
= 0, co_count
= 0, flop_count
= 0;
568 for (auto cell
: boxes
) {
569 RTLIL::Module
* box_module
= design
->module(cell
->type
);
570 log_assert(box_module
);
572 if (box_module
->attributes
.count("\\abc_carry") && !abc_carry_modules
.count(box_module
)) {
573 RTLIL::Wire
* carry_in
= nullptr, *carry_out
= nullptr;
574 RTLIL::Wire
* last_in
= nullptr, *last_out
= nullptr;
575 for (const auto &port_name
: box_module
->ports
) {
576 RTLIL::Wire
* w
= box_module
->wire(port_name
);
579 if (w
->attributes
.count("\\abc_carry_in")) {
580 log_assert(!carry_in
);
583 log_assert(!last_in
|| last_in
->port_id
< w
->port_id
);
586 if (w
->port_output
) {
587 if (w
->attributes
.count("\\abc_carry_out")) {
588 log_assert(!carry_out
);
591 log_assert(!last_out
|| last_out
->port_id
< w
->port_id
);
596 if (carry_in
!= last_in
) {
597 std::swap(box_module
->ports
[carry_in
->port_id
], box_module
->ports
[last_in
->port_id
]);
598 std::swap(carry_in
->port_id
, last_in
->port_id
);
600 if (carry_out
!= last_out
) {
601 log_assert(last_out
);
602 std::swap(box_module
->ports
[carry_out
->port_id
], box_module
->ports
[last_out
->port_id
]);
603 std::swap(carry_out
->port_id
, last_out
->port_id
);
607 bool flop
= box_module
->attributes
.count("\\abc_flop");
608 log_assert(!flop
|| flop_count
< flopNum
);
610 // NB: Assume box_module->ports are sorted alphabetically
611 // (as RTLIL::Module::fixup_ports() would do)
612 for (auto port_name
: box_module
->ports
) {
613 RTLIL::Wire
* w
= box_module
->wire(port_name
);
616 RTLIL::Wire
* wire
= nullptr;
617 for (int i
= 0; i
< GetSize(w
); i
++) {
619 log_assert(co_count
< outputs
.size());
620 wire
= outputs
[co_count
++];
622 log_assert(wire
->port_output
);
623 wire
->port_output
= false;
625 if (flop
&& w
->attributes
.count("\\abc_flop_d")) {
626 RTLIL::Wire
* d
= outputs
[outputs
.size() - flopNum
+ flop_count
];
628 log_assert(d
->port_output
);
629 d
->port_output
= false;
632 if (w
->port_output
) {
633 log_assert((piNum
+ ci_count
) < inputs
.size());
634 wire
= inputs
[piNum
+ ci_count
++];
636 log_assert(wire
->port_input
);
637 wire
->port_input
= false;
639 if (flop
&& w
->attributes
.count("\\abc_flop_q")) {
640 wire
= inputs
[piNum
- flopNum
+ flop_count
];
642 log_assert(wire
->port_input
);
643 wire
->port_input
= false;
648 cell
->setPort(port_name
, rhs
);
651 if (flop
) flop_count
++;
654 dict
<RTLIL::IdString
, int> wideports_cache
;
656 if (!map_filename
.empty()) {
657 std::ifstream
mf(map_filename
);
658 std::string type
, symbol
;
660 while (mf
>> type
>> variable
>> index
>> symbol
) {
661 RTLIL::IdString escaped_s
= RTLIL::escape_id(symbol
);
662 if (type
== "input") {
663 log_assert(static_cast<unsigned>(variable
) < inputs
.size());
664 RTLIL::Wire
* wire
= inputs
[variable
];
666 log_assert(wire
->port_input
);
669 // Cope with the fact that a CI might be identical
670 // to a PI (necessary due to ABC); in those cases
671 // simply connect the latter to the former
672 RTLIL::Wire
* existing
= module
->wire(escaped_s
);
674 module
->rename(wire
, escaped_s
);
676 wire
->port_input
= false;
677 module
->connect(wire
, existing
);
680 else if (index
> 0) {
681 std::string indexed_name
= stringf("%s[%d]", escaped_s
.c_str(), index
);
682 RTLIL::Wire
* existing
= module
->wire(indexed_name
);
684 module
->rename(wire
, indexed_name
);
686 wideports_cache
[escaped_s
] = std::max(wideports_cache
[escaped_s
], index
);
689 module
->connect(wire
, existing
);
690 wire
->port_input
= false;
694 else if (type
== "output") {
695 log_assert(static_cast<unsigned>(variable
+ co_count
) < outputs
.size());
696 RTLIL::Wire
* wire
= outputs
[variable
+ co_count
];
698 log_assert(wire
->port_output
);
699 if (escaped_s
.in("\\__dummy_o__", "\\__const0__", "\\__const1__")) {
700 wire
->port_output
= false;
705 // Cope with the fact that a CO might be identical
706 // to a PO (necessary due to ABC); in those cases
707 // simply connect the latter to the former
708 RTLIL::Wire
* existing
= module
->wire(escaped_s
);
710 if (escaped_s
.ends_with("$inout.out")) {
711 wire
->port_output
= false;
712 RTLIL::Wire
*in_wire
= module
->wire(escaped_s
.substr(0, escaped_s
.size()-10));
714 log_assert(in_wire
->port_input
&& !in_wire
->port_output
);
715 in_wire
->port_output
= true;
716 module
->connect(in_wire
, wire
);
719 module
->rename(wire
, escaped_s
);
722 wire
->port_output
= false;
723 module
->connect(wire
, existing
);
726 else if (index
> 0) {
727 std::string indexed_name
= stringf("%s[%d]", escaped_s
.c_str(), index
);
728 RTLIL::Wire
* existing
= module
->wire(indexed_name
);
730 if (escaped_s
.ends_with("$inout.out")) {
731 wire
->port_output
= false;
732 RTLIL::Wire
*in_wire
= module
->wire(stringf("%s[%d]", escaped_s
.substr(0, escaped_s
.size()-10).c_str(), index
));
734 log_assert(in_wire
->port_input
&& !in_wire
->port_output
);
735 in_wire
->port_output
= true;
736 module
->connect(in_wire
, wire
);
739 module
->rename(wire
, indexed_name
);
741 wideports_cache
[escaped_s
] = std::max(wideports_cache
[escaped_s
], index
);
745 module
->connect(wire
, existing
);
746 wire
->port_output
= false;
750 else if (type
== "box") {
751 RTLIL::Cell
* cell
= module
->cell(stringf("$__box%d__", variable
));
752 if (cell
) { // ABC could have optimised this box away
753 module
->rename(cell
, escaped_s
);
754 RTLIL::Module
* box_module
= design
->module(cell
->type
);
755 log_assert(box_module
);
757 for (const auto &i
: cell
->connections()) {
758 RTLIL::IdString port_name
= i
.first
;
759 RTLIL::SigSpec rhs
= i
.second
;
761 for (auto bit
: rhs
.bits()) {
762 RTLIL::Wire
* wire
= bit
.wire
;
763 RTLIL::IdString escaped_s
= RTLIL::escape_id(stringf("%s.%s", log_id(cell
), log_id(port_name
)));
765 module
->rename(wire
, escaped_s
);
766 else if (index
> 0) {
767 module
->rename(wire
, stringf("%s[%d]", escaped_s
.c_str(), index
));
769 wideports_cache
[escaped_s
] = std::max(wideports_cache
[escaped_s
], index
);
777 log_error("Symbol type '%s' not recognised.\n", type
.c_str());
781 for (auto &wp
: wideports_cache
) {
782 auto name
= wp
.first
;
783 int width
= wp
.second
+ 1;
785 RTLIL::Wire
*wire
= module
->wire(name
);
787 module
->rename(wire
, RTLIL::escape_id(stringf("%s[%d]", name
.c_str(), 0)));
789 // Do not make ports with a mix of input/output into
791 bool port_input
= false, port_output
= false;
792 for (int i
= 0; i
< width
; i
++) {
793 RTLIL::IdString other_name
= name
.str() + stringf("[%d]", i
);
794 RTLIL::Wire
*other_wire
= module
->wire(other_name
);
796 port_input
= port_input
|| other_wire
->port_input
;
797 port_output
= port_output
|| other_wire
->port_output
;
800 if ((port_input
&& port_output
) || (!port_input
&& !port_output
))
803 wire
= module
->addWire(name
, width
);
804 wire
->port_input
= port_input
;
805 wire
->port_output
= port_output
;
807 for (int i
= 0; i
< width
; i
++) {
808 RTLIL::IdString other_name
= name
.str() + stringf("[%d]", i
);
809 RTLIL::Wire
*other_wire
= module
->wire(other_name
);
811 other_wire
->port_input
= false;
812 other_wire
->port_output
= false;
813 if (wire
->port_input
)
814 module
->connect(other_wire
, SigSpec(wire
, i
));
816 module
->connect(SigSpec(wire
, i
), other_wire
);
821 module
->fixup_ports();
824 design
->selection_stack
.emplace_back(false);
825 RTLIL::Selection
& sel
= design
->selection_stack
.back();
828 Pass::call(design
, "clean");
830 design
->selection_stack
.pop_back();
832 for (auto cell
: module
->cells().to_vector()) {
833 if (cell
->type
!= "$lut") continue;
834 auto y_port
= cell
->getPort("\\Y").as_bit();
835 if (y_port
.wire
->width
== 1)
836 module
->rename(cell
, stringf("%s$lut", y_port
.wire
->name
.c_str()));
838 module
->rename(cell
, stringf("%s[%d]$lut", y_port
.wire
->name
.c_str(), y_port
.offset
));
842 struct AigerFrontend
: public Frontend
{
843 AigerFrontend() : Frontend("aiger", "read AIGER file") { }
844 void help() YS_OVERRIDE
846 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
848 log(" read_aiger [options] [filename]\n");
850 log("Load module from an AIGER file into the current design.\n");
852 log(" -module_name <module_name>\n");
853 log(" Name of module to be created (default: <filename>)\n");
855 log(" -clk_name <wire_name>\n");
856 log(" AIGER latches to be transformed into posedge DFFs clocked by wire of");
857 log(" this name (default: clk)\n");
859 log(" -map <filename>\n");
860 log(" read file with port and latch symbols\n");
862 log(" -wideports\n");
863 log(" Merge ports that match the pattern 'name[int]' into a single\n");
864 log(" multi-bit port 'name'.\n");
867 void execute(std::istream
*&f
, std::string filename
, std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
869 log_header(design
, "Executing AIGER frontend.\n");
871 RTLIL::IdString clk_name
= "\\clk";
872 RTLIL::IdString module_name
;
873 std::string map_filename
;
874 bool wideports
= false;
877 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
878 std::string arg
= args
[argidx
];
879 if (arg
== "-module_name" && argidx
+1 < args
.size()) {
880 module_name
= RTLIL::escape_id(args
[++argidx
]);
883 if (arg
== "-clk_name" && argidx
+1 < args
.size()) {
884 clk_name
= RTLIL::escape_id(args
[++argidx
]);
887 if (map_filename
.empty() && arg
== "-map" && argidx
+1 < args
.size()) {
888 map_filename
= args
[++argidx
];
891 if (arg
== "-wideports") {
897 extra_args(f
, filename
, args
, argidx
);
899 if (module_name
.empty()) {
901 char fname
[_MAX_FNAME
];
902 _splitpath(filename
.c_str(), NULL
/* drive */, NULL
/* dir */, fname
, NULL
/* ext */)
905 char* bn
= strdup(filename
.c_str());
906 module_name
= RTLIL::escape_id(bn
);
911 AigerReader
reader(design
, *f
, module_name
, clk_name
, map_filename
, wideports
);
912 reader
.parse_aiger();