Remove unused function
[yosys.git] / frontends / aiger / aigerparse.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * Copyright (C) 2019 Eddie Hung <eddie@fpgeh.com>
6 *
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.
10 *
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.
18 *
19 */
20
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
24
25 #ifdef _WIN32
26 #include <libgen.h>
27 #include <stdlib.h>
28 #endif
29 #include <array>
30
31 #include "kernel/yosys.h"
32 #include "kernel/sigtools.h"
33 #include "kernel/consteval.h"
34 #include "aigerparse.h"
35
36 YOSYS_NAMESPACE_BEGIN
37
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)
40 {
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));
45 }
46
47 void AigerReader::parse_aiger()
48 {
49 std::string header;
50 f >> header;
51 if (header != "aag" && header != "aig")
52 log_error("Unsupported AIGER file!\n");
53
54 // Parse rest of header
55 if (!(f >> M >> I >> L >> O >> A))
56 log_error("Invalid AIGER header\n");
57
58 // Optional values
59 B = C = J = F = 0;
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");
68 end_of_header:
69
70 std::string line;
71 std::getline(f, line); // Ignore up to start of next line, as standard
72 // says anything that follows could be used for
73 // optional sections
74
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);
76
77 line_count = 1;
78
79 if (header == "aag")
80 parse_aiger_ascii();
81 else if (header == "aig")
82 parse_aiger_binary();
83 else
84 log_abort();
85
86 // Parse footer (symbol table, comments, etc.)
87 unsigned l1;
88 std::string s;
89 for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) {
90 if (c == 'i' || c == 'l' || c == 'o') {
91 f.ignore(1);
92 if (!(f >> l1 >> s))
93 log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count);
94
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);
97
98 RTLIL::Wire* wire;
99 if (c == 'i') wire = inputs[l1];
100 else if (c == 'l') wire = latches[l1];
101 else if (c == 'o') wire = outputs[l1];
102 else log_abort();
103
104 module->rename(wire, stringf("\\%s", s.c_str()));
105 }
106 else if (c == 'b' || c == 'j' || c == 'f') {
107 // TODO
108 }
109 else if (c == 'c') {
110 f.ignore(1);
111 if (f.peek() == '\n')
112 break;
113 // Else constraint (TODO)
114 }
115 else
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
118 }
119
120 post_process();
121 }
122
123 static uint32_t parse_xaiger_literal(std::istream &f)
124 {
125 uint32_t l;
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
130 #ifdef _WIN32
131 return _byteswap_ulong(l);
132 #else
133 return __builtin_bswap32(l);
134 #endif
135 }
136
137 static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal)
138 {
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);
150 if (wire_inv) {
151 if (module->cell(wire_inv_name)) return wire;
152 }
153 else {
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;
157 }
158
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?
161
162 return wire;
163 }
164
165 void AigerReader::parse_xaiger()
166 {
167 std::string header;
168 f >> header;
169 if (header != "aag" && header != "aig")
170 log_error("Unsupported AIGER file!\n");
171
172 // Parse rest of header
173 if (!(f >> M >> I >> L >> O >> A))
174 log_error("Invalid AIGER header\n");
175
176 // Optional values
177 B = C = J = F = 0;
178
179 std::string line;
180 std::getline(f, line); // Ignore up to start of next line, as standard
181 // says anything that follows could be used for
182 // optional sections
183
184 log_debug("M=%u I=%u L=%u O=%u A=%u\n", M, I, L, O, A);
185
186 line_count = 1;
187
188 if (header == "aag")
189 parse_aiger_ascii();
190 else if (header == "aig")
191 parse_aiger_binary();
192 else
193 log_abort();
194
195 // Parse footer (symbol table, comments, etc.)
196 unsigned l1;
197 std::string s;
198 bool comment_seen = false;
199 for (int c = f.peek(); c != EOF; c = f.peek()) {
200 if (comment_seen || c == 'c') {
201 if (!comment_seen) {
202 f.ignore(1);
203 c = f.peek();
204 comment_seen = true;
205 }
206 if (c == '\n')
207 break;
208 f.ignore(1);
209 // XAIGER extensions
210 if (c == 'm') {
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));
221 uint32_t nodeID;
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));
227 log_assert(wire);
228 input_sig.append(wire);
229 }
230 RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << input_sig.size());
231 for (int j = 0; j < (1 << cutLeavesM); ++j) {
232 ce.push();
233 ce.set(input_sig, RTLIL::Const{j, static_cast<int>(cutLeavesM)});
234 RTLIL::SigSpec o(output_sig);
235 ce.eval(o);
236 lut_mask[j] = o.as_const()[0];
237 ce.pop();
238 }
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));
243 }
244 }
245 else if (c == 'n') {
246 parse_xaiger_literal(f);
247 f >> s;
248 log_debug("n: '%s'\n", s.c_str());
249 }
250 else if (c == 'a' || c == 'i' || c == 'o' || c == 'h') {
251 uint32_t dataSize = parse_xaiger_literal(f);
252 f.ignore(dataSize);
253 }
254 else {
255 break;
256 }
257 }
258 else
259 log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c);
260 }
261
262 post_process();
263 }
264
265 void AigerReader::parse_aiger_ascii()
266 {
267 std::string line;
268 std::stringstream ss;
269
270 unsigned l1, l2, l3;
271
272 // Parse inputs
273 for (unsigned i = 0; i < I; ++i, ++line_count) {
274 if (!(f >> l1))
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);
281 }
282
283 // Parse latches
284 RTLIL::Wire *clk_wire = nullptr;
285 if (L > 0) {
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;
293 }
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);
301
302 module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire);
303
304 // Reset logic is optional in AIGER 1.9
305 if (f.peek() == ' ') {
306 if (!(f >> l3))
307 log_error("Line %u cannot be interpreted as a latch!\n", line_count);
308
309 if (l3 == 0 || l3 == 1)
310 q_wire->attributes["\\init"] = RTLIL::Const(l3);
311 else if (l3 == l1) {
312 //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
313 }
314 else
315 log_error("Line %u has invalid reset literal for latch!\n", line_count);
316 }
317 else {
318 // AIGER latches are assumed to be initialized to zero
319 q_wire->attributes["\\init"] = RTLIL::Const(0);
320 }
321 latches.push_back(q_wire);
322 }
323
324 // Parse outputs
325 for (unsigned i = 0; i < O; ++i, ++line_count) {
326 if (!(f >> l1))
327 log_error("Line %u cannot be interpreted as an output!\n", line_count);
328
329 RTLIL::Wire *wire;
330 if (l1 == 0 || l1 == 1) {
331 wire = module->addWire(NEW_ID);
332 if (l1 == 0)
333 module->connect(wire, RTLIL::State::S0);
334 else if (l1 == 1)
335 module->connect(wire, RTLIL::State::S1);
336 else
337 log_abort();
338 }
339 else {
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);
345 if (!wire)
346 wire = createWireIfNotExists(module, l1);
347 else {
348 if (wire->port_input || wire->port_output) {
349 RTLIL::Wire *new_wire = module->addWire(NEW_ID);
350 module->connect(new_wire, wire);
351 wire = new_wire;
352 }
353 }
354 }
355 wire->port_output = true;
356 outputs.push_back(wire);
357 }
358 std::getline(f, line); // Ignore up to start of next line
359
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
363
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
367
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
371
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
375
376 // Parse AND
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);
380
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);
387 }
388 std::getline(f, line); // Ignore up to start of next line
389 }
390
391 static unsigned parse_next_delta_literal(std::istream &f, unsigned ref)
392 {
393 unsigned x = 0, i = 0;
394 unsigned char ch;
395 while ((ch = f.get()) & 0x80)
396 x |= (ch & 0x7f) << (7 * i++);
397 return ref - (x | (ch << (7 * i)));
398 }
399
400 void AigerReader::parse_aiger_binary()
401 {
402 unsigned l1, l2, l3;
403 std::string line;
404
405 // Parse inputs
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);
412 }
413
414 // Parse latches
415 RTLIL::Wire *clk_wire = nullptr;
416 if (L > 0) {
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;
424 }
425 l1 = (I+1) * 2;
426 for (unsigned i = 0; i < L; ++i, ++line_count, l1 += 2) {
427 if (!(f >> l2))
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);
432
433 module->addDff(NEW_ID, clk_wire, d_wire, q_wire);
434
435 // Reset logic is optional in AIGER 1.9
436 if (f.peek() == ' ') {
437 if (!(f >> l3))
438 log_error("Line %u cannot be interpreted as a latch!\n", line_count);
439
440 if (l3 == 0 || l3 == 1)
441 q_wire->attributes["\\init"] = RTLIL::Const(l3);
442 else if (l3 == l1) {
443 //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
444 }
445 else
446 log_error("Line %u has invalid reset literal for latch!\n", line_count);
447 }
448 else {
449 // AIGER latches are assumed to be initialized to zero
450 q_wire->attributes["\\init"] = RTLIL::Const(0);
451 }
452 latches.push_back(q_wire);
453 }
454
455 // Parse outputs
456 for (unsigned i = 0; i < O; ++i, ++line_count) {
457 if (!(f >> l1))
458 log_error("Line %u cannot be interpreted as an output!\n", line_count);
459
460 RTLIL::Wire *wire;
461 if (l1 == 0 || l1 == 1) {
462 wire = module->addWire(NEW_ID);
463 if (l1 == 0)
464 module->connect(wire, RTLIL::State::S0);
465 else if (l1 == 1)
466 module->connect(wire, RTLIL::State::S1);
467 else
468 log_abort();
469 }
470 else {
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);
476 if (!wire)
477 wire = createWireIfNotExists(module, l1);
478 else {
479 if (wire->port_input || wire->port_output) {
480 RTLIL::Wire *new_wire = module->addWire(NEW_ID);
481 module->connect(new_wire, wire);
482 wire = new_wire;
483 }
484 }
485 }
486 wire->port_output = true;
487 outputs.push_back(wire);
488 }
489 std::getline(f, line); // Ignore up to start of next line
490
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
494
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
498
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
502
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
506
507 // Parse AND
508 l1 = (I+L+1) << 1;
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);
512
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);
519 }
520 }
521
522 void AigerReader::post_process()
523 {
524 dict<RTLIL::IdString, int> wideports_cache;
525
526 if (!map_filename.empty()) {
527 std::ifstream mf(map_filename);
528 std::string type, symbol;
529 int variable, index;
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];
535 log_assert(wire);
536 log_assert(wire->port_input);
537
538 if (index == 0) {
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);
543 if (!existing)
544 module->rename(wire, escaped_s);
545 else {
546 wire->port_input = false;
547 module->connect(wire, existing);
548 }
549 }
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);
553 if (!existing) {
554 module->rename(wire, indexed_name);
555 if (wideports)
556 wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index);
557 }
558 else {
559 module->connect(wire, existing);
560 wire->port_input = false;
561 }
562 }
563 }
564 else if (type == "output") {
565 log_assert(static_cast<unsigned>(variable) < outputs.size());
566 RTLIL::Wire* wire = outputs[variable];
567 log_assert(wire);
568 log_assert(wire->port_output);
569 if (escaped_s.in("\\__dummy_o__", "\\__const0__", "\\__const1__")) {
570 wire->port_output = false;
571 continue;
572 }
573
574 if (index == 0) {
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);
579 if (!existing) {
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));
583 log_assert(in_wire);
584 log_assert(in_wire->port_input && !in_wire->port_output);
585 in_wire->port_output = true;
586 module->connect(in_wire, wire);
587 }
588 else
589 module->rename(wire, escaped_s);
590 }
591 else {
592 wire->port_output = false;
593 module->connect(wire, existing);
594 }
595 }
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);
599 if (!existing) {
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));
603 log_assert(in_wire);
604 log_assert(in_wire->port_input && !in_wire->port_output);
605 in_wire->port_output = true;
606 module->connect(in_wire, wire);
607 }
608 else {
609 module->rename(wire, indexed_name);
610 if (wideports)
611 wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index);
612 }
613 }
614 else {
615 module->connect(wire, existing);
616 wire->port_output = false;
617 }
618 }
619 }
620 else if (type == "cinput" || type == "coutput") {
621 RTLIL::Wire* wire;
622 if (type == "cinput") {
623 log_assert(static_cast<unsigned>(variable) < inputs.size());
624 wire = inputs[variable];
625 log_assert(wire);
626 log_assert(wire->port_input);
627 }
628 else if (type == "coutput") {
629 log_assert(static_cast<unsigned>(variable) < outputs.size());
630 wire = outputs[variable];
631 log_assert(wire);
632 log_assert(wire->port_output);
633 }
634 else log_abort();
635
636 std::string port, type;
637 mf >> 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);
641
642 RTLIL::Cell* cell = module->cell(cell_name);
643 if (!cell)
644 cell = module->addCell(cell_name, cell_type);
645 else
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);
652 }
653 else {
654 log_assert(index == 0);
655 cell->setPort(cell_port, wire);
656 }
657 }
658 else
659 log_error("Symbol type '%s' not recognised.\n", type.c_str());
660 }
661 }
662
663 for (auto &wp : wideports_cache) {
664 auto name = wp.first;
665 int width = wp.second + 1;
666
667 RTLIL::Wire *wire = module->wire(name);
668 if (wire)
669 module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0)));
670
671 // Do not make ports with a mix of input/output into
672 // wide ports
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);
677 if (other_wire) {
678 port_input = port_input || other_wire->port_input;
679 port_output = port_output || other_wire->port_output;
680 }
681 }
682 if ((port_input && port_output) || (!port_input && !port_output))
683 continue;
684
685 wire = module->addWire(name, width);
686 wire->port_input = port_input;
687 wire->port_output = port_output;
688
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);
692 if (other_wire) {
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));
697 else
698 module->connect(SigSpec(wire, i), other_wire);
699 }
700 }
701 }
702
703 module->fixup_ports();
704 design->add(module);
705
706 Pass::call(design, "clean");
707
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()));
713 else
714 module->rename(cell, stringf("%s[%d]$lut", y_port.wire->name.c_str(), y_port.offset));
715 }
716 }
717
718 struct AigerFrontend : public Frontend {
719 AigerFrontend() : Frontend("aiger", "read AIGER file") { }
720 void help() YS_OVERRIDE
721 {
722 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
723 log("\n");
724 log(" read_aiger [options] [filename]\n");
725 log("\n");
726 log("Load module from an AIGER file into the current design.\n");
727 log("\n");
728 log(" -module_name <module_name>\n");
729 log(" Name of module to be created (default: <filename>)\n");
730 log("\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");
734 log("\n");
735 log(" -map <filename>\n");
736 log(" read file with port and latch symbols\n");
737 log("\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");
741 log("\n");
742 }
743 void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
744 {
745 log_header(design, "Executing AIGER frontend.\n");
746
747 RTLIL::IdString clk_name = "\\clk";
748 RTLIL::IdString module_name;
749 std::string map_filename;
750 bool wideports = false;
751
752 size_t argidx;
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]);
757 continue;
758 }
759 if (arg == "-clk_name" && argidx+1 < args.size()) {
760 clk_name = RTLIL::escape_id(args[++argidx]);
761 continue;
762 }
763 if (map_filename.empty() && arg == "-map" && argidx+1 < args.size()) {
764 map_filename = args[++argidx];
765 continue;
766 }
767 if (arg == "-wideports") {
768 wideports = true;
769 continue;
770 }
771 break;
772 }
773 extra_args(f, filename, args, argidx);
774
775 if (module_name.empty()) {
776 #ifdef _WIN32
777 char fname[_MAX_FNAME];
778 _splitpath(filename.c_str(), NULL /* drive */, NULL /* dir */, fname, NULL /* ext */)
779 module_name = fname;
780 #else
781 char* bn = strdup(filename.c_str());
782 module_name = RTLIL::escape_id(bn);
783 free(bn);
784 #endif
785 }
786
787 AigerReader reader(design, *f, module_name, clk_name, map_filename, wideports);
788 reader.parse_aiger();
789 }
790 } AigerFrontend;
791
792 YOSYS_NAMESPACE_END