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
);
81 else if (header
== "aig")
86 // Parse footer (symbol table, comments, etc.)
89 for (int c
= f
.peek(); c
!= EOF
; c
= f
.peek(), ++line_count
) {
90 if (c
== 'i' || c
== 'l' || c
== 'o') {
93 log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count
);
95 if ((c
== 'i' && l1
> inputs
.size()) || (c
== 'l' && l1
> latches
.size()) || (c
== 'o' && l1
> outputs
.size()))
96 log_error("Line %u has invalid symbol position!\n", line_count
);
99 if (c
== 'i') wire
= inputs
[l1
];
100 else if (c
== 'l') wire
= latches
[l1
];
101 else if (c
== 'o') wire
= outputs
[l1
];
104 module
->rename(wire
, stringf("\\%s", s
.c_str()));
106 else if (c
== 'b' || c
== 'j' || c
== 'f') {
111 if (f
.peek() == '\n')
113 // Else constraint (TODO)
116 log_error("Line %u: cannot interpret first character '%c'!\n", line_count
, c
);
117 std::getline(f
, line
); // Ignore up to start of next line
123 static uint32_t parse_xaiger_literal(std::istream
&f
)
126 f
.read(reinterpret_cast<char*>(&l
), sizeof(l
));
127 if (f
.gcount() != sizeof(l
))
128 log_error("Offset %ld: unable to read literal!\n", static_cast<int64_t>(f
.tellg()));
129 // TODO: Don't assume we're on little endian
131 return _byteswap_ulong(l
);
133 return __builtin_bswap32(l
);
137 static RTLIL::Wire
* createWireIfNotExists(RTLIL::Module
*module
, unsigned literal
)
139 const unsigned variable
= literal
>> 1;
140 const bool invert
= literal
& 1;
141 RTLIL::IdString
wire_name(stringf("\\__%d%s__", variable
, invert
? "b" : "")); // FIXME: is "b" the right suffix?
142 RTLIL::Wire
*wire
= module
->wire(wire_name
);
143 if (wire
) return wire
;
144 log_debug("Creating %s\n", wire_name
.c_str());
145 wire
= module
->addWire(wire_name
);
146 wire
->port_input
= wire
->port_output
= false;
147 if (!invert
) return wire
;
148 RTLIL::IdString
wire_inv_name(stringf("\\__%d__", variable
));
149 RTLIL::Wire
*wire_inv
= module
->wire(wire_inv_name
);
151 if (module
->cell(wire_inv_name
)) return wire
;
154 log_debug("Creating %s\n", wire_inv_name
.c_str());
155 wire_inv
= module
->addWire(wire_inv_name
);
156 wire_inv
->port_input
= wire_inv
->port_output
= false;
159 log_debug("Creating %s = ~%s\n", wire_name
.c_str(), wire_inv_name
.c_str());
160 module
->addNotGate(stringf("\\__%d__$not", variable
), wire_inv
, wire
); // FIXME: is "$not" the right suffix?
165 void AigerReader::parse_xaiger()
169 if (header
!= "aag" && header
!= "aig")
170 log_error("Unsupported AIGER file!\n");
172 // Parse rest of header
173 if (!(f
>> M
>> I
>> L
>> O
>> A
))
174 log_error("Invalid AIGER header\n");
180 std::getline(f
, line
); // Ignore up to start of next line, as standard
181 // says anything that follows could be used for
184 log_debug("M=%u I=%u L=%u O=%u A=%u\n", M
, I
, L
, O
, A
);
190 else if (header
== "aig")
191 parse_aiger_binary();
195 // Parse footer (symbol table, comments, etc.)
198 bool comment_seen
= false;
199 for (int c
= f
.peek(); c
!= EOF
; c
= f
.peek()) {
200 if (comment_seen
|| c
== 'c') {
211 uint32_t dataSize
= parse_xaiger_literal(f
);
212 uint32_t lutNum
= parse_xaiger_literal(f
);
213 uint32_t lutSize
= parse_xaiger_literal(f
);
214 log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize
, lutNum
, lutSize
);
215 ConstEval
ce(module
);
216 for (unsigned i
= 0; i
< lutNum
; ++i
) {
217 uint32_t rootNodeID
= parse_xaiger_literal(f
);
218 uint32_t cutLeavesM
= parse_xaiger_literal(f
);
219 log_debug("rootNodeID=%d cutLeavesM=%d\n", rootNodeID
, cutLeavesM
);
220 RTLIL::Wire
*output_sig
= module
->wire(stringf("\\__%d__", rootNodeID
));
222 RTLIL::SigSpec input_sig
;
223 for (unsigned j
= 0; j
< cutLeavesM
; ++j
) {
224 nodeID
= parse_xaiger_literal(f
);
225 log_debug("\t%u\n", nodeID
);
226 RTLIL::Wire
*wire
= module
->wire(stringf("\\__%d__", nodeID
));
228 input_sig
.append(wire
);
230 RTLIL::Const
lut_mask(RTLIL::State::Sx
, 1 << input_sig
.size());
231 for (int j
= 0; j
< (1 << cutLeavesM
); ++j
) {
233 ce
.set(input_sig
, RTLIL::Const
{j
, static_cast<int>(cutLeavesM
)});
234 RTLIL::SigSpec
o(output_sig
);
236 lut_mask
[j
] = o
.as_const()[0];
239 RTLIL::Cell
*output_cell
= module
->cell(stringf("\\__%d__$and", rootNodeID
));
240 log_assert(output_cell
);
241 module
->remove(output_cell
);
242 module
->addLut(stringf("\\__%d__$lut", rootNodeID
), input_sig
, output_sig
, std::move(lut_mask
));
246 parse_xaiger_literal(f
);
248 log_debug("n: '%s'\n", s
.c_str());
250 else if (c
== 'a' || c
== 'i' || c
== 'o' || c
== 'h') {
251 uint32_t dataSize
= parse_xaiger_literal(f
);
259 log_error("Line %u: cannot interpret first character '%c'!\n", line_count
, c
);
265 void AigerReader::parse_aiger_ascii()
268 std::stringstream ss
;
273 for (unsigned i
= 0; i
< I
; ++i
, ++line_count
) {
275 log_error("Line %u cannot be interpreted as an input!\n", line_count
);
276 log_debug("%d is an input\n", l1
);
277 log_assert(!(l1
& 1)); // Inputs can't be inverted
278 RTLIL::Wire
*wire
= createWireIfNotExists(module
, l1
);
279 wire
->port_input
= true;
280 inputs
.push_back(wire
);
284 RTLIL::Wire
*clk_wire
= nullptr;
286 log_assert(clk_name
!= "");
287 clk_wire
= module
->wire(clk_name
);
288 log_assert(!clk_wire
);
289 log_debug("Creating %s\n", clk_name
.c_str());
290 clk_wire
= module
->addWire(clk_name
);
291 clk_wire
->port_input
= true;
292 clk_wire
->port_output
= false;
294 for (unsigned i
= 0; i
< L
; ++i
, ++line_count
) {
295 if (!(f
>> l1
>> l2
))
296 log_error("Line %u cannot be interpreted as a latch!\n", line_count
);
297 log_debug("%d %d is a latch\n", l1
, l2
);
298 log_assert(!(l1
& 1)); // TODO: Latch outputs can't be inverted?
299 RTLIL::Wire
*q_wire
= createWireIfNotExists(module
, l1
);
300 RTLIL::Wire
*d_wire
= createWireIfNotExists(module
, l2
);
302 module
->addDffGate(NEW_ID
, clk_wire
, d_wire
, q_wire
);
304 // Reset logic is optional in AIGER 1.9
305 if (f
.peek() == ' ') {
307 log_error("Line %u cannot be interpreted as a latch!\n", line_count
);
309 if (l3
== 0 || l3
== 1)
310 q_wire
->attributes
["\\init"] = RTLIL::Const(l3
);
312 //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
315 log_error("Line %u has invalid reset literal for latch!\n", line_count
);
318 // AIGER latches are assumed to be initialized to zero
319 q_wire
->attributes
["\\init"] = RTLIL::Const(0);
321 latches
.push_back(q_wire
);
325 for (unsigned i
= 0; i
< O
; ++i
, ++line_count
) {
327 log_error("Line %u cannot be interpreted as an output!\n", line_count
);
330 if (l1
== 0 || l1
== 1) {
331 wire
= module
->addWire(NEW_ID
);
333 module
->connect(wire
, RTLIL::State::S0
);
335 module
->connect(wire
, RTLIL::State::S1
);
340 log_debug("%d is an output\n", l1
);
341 const unsigned variable
= l1
>> 1;
342 const bool invert
= l1
& 1;
343 RTLIL::IdString
wire_name(stringf("\\__%d%s__", variable
, invert
? "b" : "")); // FIXME: is "b" the right suffix?
344 wire
= module
->wire(wire_name
);
346 wire
= createWireIfNotExists(module
, l1
);
348 if (wire
->port_input
|| wire
->port_output
) {
349 RTLIL::Wire
*new_wire
= module
->addWire(NEW_ID
);
350 module
->connect(new_wire
, wire
);
355 wire
->port_output
= true;
356 outputs
.push_back(wire
);
358 std::getline(f
, line
); // Ignore up to start of next line
360 // TODO: Parse bad state properties
361 for (unsigned i
= 0; i
< B
; ++i
, ++line_count
)
362 std::getline(f
, line
); // Ignore up to start of next line
364 // TODO: Parse invariant constraints
365 for (unsigned i
= 0; i
< C
; ++i
, ++line_count
)
366 std::getline(f
, line
); // Ignore up to start of next line
368 // TODO: Parse justice properties
369 for (unsigned i
= 0; i
< J
; ++i
, ++line_count
)
370 std::getline(f
, line
); // Ignore up to start of next line
372 // TODO: Parse fairness constraints
373 for (unsigned i
= 0; i
< F
; ++i
, ++line_count
)
374 std::getline(f
, line
); // Ignore up to start of next line
377 for (unsigned i
= 0; i
< A
; ++i
) {
378 if (!(f
>> l1
>> l2
>> l3
))
379 log_error("Line %u cannot be interpreted as an AND!\n", line_count
);
381 log_debug("%d %d %d is an AND\n", l1
, l2
, l3
);
382 log_assert(!(l1
& 1));
383 RTLIL::Wire
*o_wire
= createWireIfNotExists(module
, l1
);
384 RTLIL::Wire
*i1_wire
= createWireIfNotExists(module
, l2
);
385 RTLIL::Wire
*i2_wire
= createWireIfNotExists(module
, l3
);
386 module
->addAndGate(o_wire
->name
.str() + "$and", i1_wire
, i2_wire
, o_wire
);
388 std::getline(f
, line
); // Ignore up to start of next line
391 static unsigned parse_next_delta_literal(std::istream
&f
, unsigned ref
)
393 unsigned x
= 0, i
= 0;
395 while ((ch
= f
.get()) & 0x80)
396 x
|= (ch
& 0x7f) << (7 * i
++);
397 return ref
- (x
| (ch
<< (7 * i
)));
400 void AigerReader::parse_aiger_binary()
406 for (unsigned i
= 1; i
<= I
; ++i
) {
407 log_debug("%d is an input\n", i
);
408 RTLIL::Wire
*wire
= createWireIfNotExists(module
, i
<< 1);
409 wire
->port_input
= true;
410 log_assert(!wire
->port_output
);
411 inputs
.push_back(wire
);
415 RTLIL::Wire
*clk_wire
= nullptr;
417 log_assert(clk_name
!= "");
418 clk_wire
= module
->wire(clk_name
);
419 log_assert(!clk_wire
);
420 log_debug("Creating %s\n", clk_name
.c_str());
421 clk_wire
= module
->addWire(clk_name
);
422 clk_wire
->port_input
= true;
423 clk_wire
->port_output
= false;
426 for (unsigned i
= 0; i
< L
; ++i
, ++line_count
, l1
+= 2) {
428 log_error("Line %u cannot be interpreted as a latch!\n", line_count
);
429 log_debug("%d %d is a latch\n", l1
, l2
);
430 RTLIL::Wire
*q_wire
= createWireIfNotExists(module
, l1
);
431 RTLIL::Wire
*d_wire
= createWireIfNotExists(module
, l2
);
433 module
->addDff(NEW_ID
, clk_wire
, d_wire
, q_wire
);
435 // Reset logic is optional in AIGER 1.9
436 if (f
.peek() == ' ') {
438 log_error("Line %u cannot be interpreted as a latch!\n", line_count
);
440 if (l3
== 0 || l3
== 1)
441 q_wire
->attributes
["\\init"] = RTLIL::Const(l3
);
443 //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
446 log_error("Line %u has invalid reset literal for latch!\n", line_count
);
449 // AIGER latches are assumed to be initialized to zero
450 q_wire
->attributes
["\\init"] = RTLIL::Const(0);
452 latches
.push_back(q_wire
);
456 for (unsigned i
= 0; i
< O
; ++i
, ++line_count
) {
458 log_error("Line %u cannot be interpreted as an output!\n", line_count
);
461 if (l1
== 0 || l1
== 1) {
462 wire
= module
->addWire(NEW_ID
);
464 module
->connect(wire
, RTLIL::State::S0
);
466 module
->connect(wire
, RTLIL::State::S1
);
471 log_debug("%d is an output\n", l1
);
472 const unsigned variable
= l1
>> 1;
473 const bool invert
= l1
& 1;
474 RTLIL::IdString
wire_name(stringf("\\__%d%s__", variable
, invert
? "b" : "")); // FIXME: is "_inv" the right suffix?
475 wire
= module
->wire(wire_name
);
477 wire
= createWireIfNotExists(module
, l1
);
479 if (wire
->port_input
|| wire
->port_output
) {
480 RTLIL::Wire
*new_wire
= module
->addWire(NEW_ID
);
481 module
->connect(new_wire
, wire
);
486 wire
->port_output
= true;
487 outputs
.push_back(wire
);
489 std::getline(f
, line
); // Ignore up to start of next line
491 // TODO: Parse bad state properties
492 for (unsigned i
= 0; i
< B
; ++i
, ++line_count
)
493 std::getline(f
, line
); // Ignore up to start of next line
495 // TODO: Parse invariant constraints
496 for (unsigned i
= 0; i
< C
; ++i
, ++line_count
)
497 std::getline(f
, line
); // Ignore up to start of next line
499 // TODO: Parse justice properties
500 for (unsigned i
= 0; i
< J
; ++i
, ++line_count
)
501 std::getline(f
, line
); // Ignore up to start of next line
503 // TODO: Parse fairness constraints
504 for (unsigned i
= 0; i
< F
; ++i
, ++line_count
)
505 std::getline(f
, line
); // Ignore up to start of next line
509 for (unsigned i
= 0; i
< A
; ++i
, ++line_count
, l1
+= 2) {
510 l2
= parse_next_delta_literal(f
, l1
);
511 l3
= parse_next_delta_literal(f
, l2
);
513 log_debug("%d %d %d is an AND\n", l1
, l2
, l3
);
514 log_assert(!(l1
& 1));
515 RTLIL::Wire
*o_wire
= createWireIfNotExists(module
, l1
);
516 RTLIL::Wire
*i1_wire
= createWireIfNotExists(module
, l2
);
517 RTLIL::Wire
*i2_wire
= createWireIfNotExists(module
, l3
);
518 module
->addAndGate(o_wire
->name
.str() + "$and", i1_wire
, i2_wire
, o_wire
);
522 void AigerReader::post_process()
524 dict
<RTLIL::IdString
, int> wideports_cache
;
526 if (!map_filename
.empty()) {
527 std::ifstream
mf(map_filename
);
528 std::string type
, symbol
;
530 while (mf
>> type
>> variable
>> index
>> symbol
) {
531 RTLIL::IdString escaped_s
= RTLIL::escape_id(symbol
);
532 if (type
== "input") {
533 log_assert(static_cast<unsigned>(variable
) < inputs
.size());
534 RTLIL::Wire
* wire
= inputs
[variable
];
536 log_assert(wire
->port_input
);
539 // Cope with the fact that a CI might be identical
540 // to a PI (necessary due to ABC); in those cases
541 // simply connect the latter to the former
542 RTLIL::Wire
* existing
= module
->wire(escaped_s
);
544 module
->rename(wire
, escaped_s
);
546 wire
->port_input
= false;
547 module
->connect(wire
, existing
);
550 else if (index
> 0) {
551 std::string indexed_name
= stringf("%s[%d]", escaped_s
.c_str(), index
);
552 RTLIL::Wire
* existing
= module
->wire(indexed_name
);
554 module
->rename(wire
, indexed_name
);
556 wideports_cache
[escaped_s
] = std::max(wideports_cache
[escaped_s
], index
);
559 module
->connect(wire
, existing
);
560 wire
->port_input
= false;
564 else if (type
== "output") {
565 log_assert(static_cast<unsigned>(variable
) < outputs
.size());
566 RTLIL::Wire
* wire
= outputs
[variable
];
568 log_assert(wire
->port_output
);
569 if (escaped_s
.in("\\__dummy_o__", "\\__const0__", "\\__const1__")) {
570 wire
->port_output
= false;
575 // Cope with the fact that a CO might be identical
576 // to a PO (necessary due to ABC); in those cases
577 // simply connect the latter to the former
578 RTLIL::Wire
* existing
= module
->wire(escaped_s
);
580 if (escaped_s
.ends_with("$inout.out")) {
581 wire
->port_output
= false;
582 RTLIL::Wire
*in_wire
= module
->wire(escaped_s
.substr(0, escaped_s
.size()-10));
584 log_assert(in_wire
->port_input
&& !in_wire
->port_output
);
585 in_wire
->port_output
= true;
586 module
->connect(in_wire
, wire
);
589 module
->rename(wire
, escaped_s
);
592 wire
->port_output
= false;
593 module
->connect(wire
, existing
);
596 else if (index
> 0) {
597 std::string indexed_name
= stringf("%s[%d]", escaped_s
.c_str(), index
);
598 RTLIL::Wire
* existing
= module
->wire(indexed_name
);
600 if (escaped_s
.ends_with("$inout.out")) {
601 wire
->port_output
= false;
602 RTLIL::Wire
*in_wire
= module
->wire(stringf("%s[%d]", escaped_s
.substr(0, escaped_s
.size()-10).c_str(), index
));
604 log_assert(in_wire
->port_input
&& !in_wire
->port_output
);
605 in_wire
->port_output
= true;
606 module
->connect(in_wire
, wire
);
609 module
->rename(wire
, indexed_name
);
611 wideports_cache
[escaped_s
] = std::max(wideports_cache
[escaped_s
], index
);
615 module
->connect(wire
, existing
);
616 wire
->port_output
= false;
620 else if (type
== "cinput" || type
== "coutput") {
622 if (type
== "cinput") {
623 log_assert(static_cast<unsigned>(variable
) < inputs
.size());
624 wire
= inputs
[variable
];
626 log_assert(wire
->port_input
);
628 else if (type
== "coutput") {
629 log_assert(static_cast<unsigned>(variable
) < outputs
.size());
630 wire
= outputs
[variable
];
632 log_assert(wire
->port_output
);
636 std::string port
, type
;
638 RTLIL::IdString cell_name
= RTLIL::escape_id(symbol
);
639 RTLIL::IdString cell_port
= RTLIL::escape_id(port
);
640 RTLIL::IdString cell_type
= RTLIL::escape_id(type
);
642 RTLIL::Cell
* cell
= module
->cell(cell_name
);
644 cell
= module
->addCell(cell_name
, cell_type
);
646 log_assert(cell
->type
== cell_type
);
647 wire
->port_input
= false;
648 wire
->port_output
= false;
649 if (cell
->hasPort(cell_port
)) {
650 log_assert(index
== GetSize(cell
->getPort(cell_port
)));
651 cell
->connections_
[cell_port
].append(wire
);
654 log_assert(index
== 0);
655 cell
->setPort(cell_port
, wire
);
659 log_error("Symbol type '%s' not recognised.\n", type
.c_str());
663 for (auto &wp
: wideports_cache
) {
664 auto name
= wp
.first
;
665 int width
= wp
.second
+ 1;
667 RTLIL::Wire
*wire
= module
->wire(name
);
669 module
->rename(wire
, RTLIL::escape_id(stringf("%s[%d]", name
.c_str(), 0)));
671 // Do not make ports with a mix of input/output into
673 bool port_input
= false, port_output
= false;
674 for (int i
= 0; i
< width
; i
++) {
675 RTLIL::IdString other_name
= name
.str() + stringf("[%d]", i
);
676 RTLIL::Wire
*other_wire
= module
->wire(other_name
);
678 port_input
= port_input
|| other_wire
->port_input
;
679 port_output
= port_output
|| other_wire
->port_output
;
682 if ((port_input
&& port_output
) || (!port_input
&& !port_output
))
685 wire
= module
->addWire(name
, width
);
686 wire
->port_input
= port_input
;
687 wire
->port_output
= port_output
;
689 for (int i
= 0; i
< width
; i
++) {
690 RTLIL::IdString other_name
= name
.str() + stringf("[%d]", i
);
691 RTLIL::Wire
*other_wire
= module
->wire(other_name
);
693 other_wire
->port_input
= false;
694 other_wire
->port_output
= false;
695 if (wire
->port_input
)
696 module
->connect(other_wire
, SigSpec(wire
, i
));
698 module
->connect(SigSpec(wire
, i
), other_wire
);
703 module
->fixup_ports();
706 Pass::call(design
, "clean");
708 for (auto cell
: module
->cells().to_vector()) {
709 if (cell
->type
!= "$lut") continue;
710 auto y_port
= cell
->getPort("\\Y").as_bit();
711 if (y_port
.wire
->width
== 1)
712 module
->rename(cell
, stringf("%s$lut", y_port
.wire
->name
.c_str()));
714 module
->rename(cell
, stringf("%s[%d]$lut", y_port
.wire
->name
.c_str(), y_port
.offset
));
718 struct AigerFrontend
: public Frontend
{
719 AigerFrontend() : Frontend("aiger", "read AIGER file") { }
720 void help() YS_OVERRIDE
722 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
724 log(" read_aiger [options] [filename]\n");
726 log("Load module from an AIGER file into the current design.\n");
728 log(" -module_name <module_name>\n");
729 log(" Name of module to be created (default: <filename>)\n");
731 log(" -clk_name <wire_name>\n");
732 log(" AIGER latches to be transformed into posedge DFFs clocked by wire of");
733 log(" this name (default: clk)\n");
735 log(" -map <filename>\n");
736 log(" read file with port and latch symbols\n");
738 log(" -wideports\n");
739 log(" Merge ports that match the pattern 'name[int]' into a single\n");
740 log(" multi-bit port 'name'.\n");
743 void execute(std::istream
*&f
, std::string filename
, std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
745 log_header(design
, "Executing AIGER frontend.\n");
747 RTLIL::IdString clk_name
= "\\clk";
748 RTLIL::IdString module_name
;
749 std::string map_filename
;
750 bool wideports
= false;
753 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
754 std::string arg
= args
[argidx
];
755 if (arg
== "-module_name" && argidx
+1 < args
.size()) {
756 module_name
= RTLIL::escape_id(args
[++argidx
]);
759 if (arg
== "-clk_name" && argidx
+1 < args
.size()) {
760 clk_name
= RTLIL::escape_id(args
[++argidx
]);
763 if (map_filename
.empty() && arg
== "-map" && argidx
+1 < args
.size()) {
764 map_filename
= args
[++argidx
];
767 if (arg
== "-wideports") {
773 extra_args(f
, filename
, args
, argidx
);
775 if (module_name
.empty()) {
777 char fname
[_MAX_FNAME
];
778 _splitpath(filename
.c_str(), NULL
/* drive */, NULL
/* dir */, fname
, NULL
/* ext */)
781 char* bn
= strdup(filename
.c_str());
782 module_name
= RTLIL::escape_id(bn
);
787 AigerReader
reader(design
, *f
, module_name
, clk_name
, map_filename
, wideports
);
788 reader
.parse_aiger();