e8a355671751f8b44adf7c23facebe64cc9afec9
[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 dict<int,IdString> box_lookup;
196 for (auto m : design->modules()) {
197 auto it = m->attributes.find("\\abc_box_id");
198 if (it == m->attributes.end())
199 continue;
200 box_lookup[it->second.as_int()] = m->name;
201 }
202
203 // Parse footer (symbol table, comments, etc.)
204 std::string s;
205 bool comment_seen = false;
206 for (int c = f.peek(); c != EOF; c = f.peek()) {
207 if (comment_seen || c == 'c') {
208 if (!comment_seen) {
209 f.ignore(1);
210 c = f.peek();
211 comment_seen = true;
212 }
213 if (c == '\n')
214 break;
215 f.ignore(1);
216 // XAIGER extensions
217 if (c == 'm') {
218 uint32_t dataSize = parse_xaiger_literal(f);
219 uint32_t lutNum = parse_xaiger_literal(f);
220 uint32_t lutSize = parse_xaiger_literal(f);
221 log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize);
222 ConstEval ce(module);
223 for (unsigned i = 0; i < lutNum; ++i) {
224 uint32_t rootNodeID = parse_xaiger_literal(f);
225 uint32_t cutLeavesM = parse_xaiger_literal(f);
226 log_debug("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM);
227 RTLIL::Wire *output_sig = module->wire(stringf("\\__%d__", rootNodeID));
228 uint32_t nodeID;
229 RTLIL::SigSpec input_sig;
230 for (unsigned j = 0; j < cutLeavesM; ++j) {
231 nodeID = parse_xaiger_literal(f);
232 log_debug("\t%u\n", nodeID);
233 RTLIL::Wire *wire = module->wire(stringf("\\__%d__", nodeID));
234 log_assert(wire);
235 input_sig.append(wire);
236 }
237 RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << input_sig.size());
238 for (int j = 0; j < (1 << cutLeavesM); ++j) {
239 ce.push();
240 ce.set(input_sig, RTLIL::Const{j, static_cast<int>(cutLeavesM)});
241 RTLIL::SigSpec o(output_sig);
242 ce.eval(o);
243 lut_mask[j] = o.as_const()[0];
244 ce.pop();
245 }
246 RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__$and", rootNodeID));
247 log_assert(output_cell);
248 module->remove(output_cell);
249 module->addLut(stringf("\\__%d__$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask));
250 }
251 }
252 else if (c == 'n') {
253 parse_xaiger_literal(f);
254 f >> s;
255 log_debug("n: '%s'\n", s.c_str());
256 }
257 else if (c == 'h') {
258 f.ignore(sizeof(uint32_t));
259 uint32_t version = parse_xaiger_literal(f);
260 log_assert(version == 1);
261 f.ignore(4*sizeof(uint32_t));
262 uint32_t boxNum = parse_xaiger_literal(f);
263 for (unsigned i = 0; i < boxNum; i++) {
264 f.ignore(2*sizeof(uint32_t));
265 uint32_t boxUniqueId = parse_xaiger_literal(f);
266 log_assert(boxUniqueId > 0);
267 uint32_t oldBoxNum = parse_xaiger_literal(f);
268 module->addCell(stringf("$__box%u__", oldBoxNum), box_lookup.at(boxUniqueId));
269 }
270 }
271 else if (c == 'a' || c == 'i' || c == 'o') {
272 uint32_t dataSize = parse_xaiger_literal(f);
273 f.ignore(dataSize);
274 }
275 else {
276 break;
277 }
278 }
279 else
280 log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c);
281 }
282
283 post_process();
284 }
285
286 void AigerReader::parse_aiger_ascii()
287 {
288 std::string line;
289 std::stringstream ss;
290
291 unsigned l1, l2, l3;
292
293 // Parse inputs
294 for (unsigned i = 0; i < I; ++i, ++line_count) {
295 if (!(f >> l1))
296 log_error("Line %u cannot be interpreted as an input!\n", line_count);
297 log_debug("%d is an input\n", l1);
298 log_assert(!(l1 & 1)); // Inputs can't be inverted
299 RTLIL::Wire *wire = createWireIfNotExists(module, l1);
300 wire->port_input = true;
301 inputs.push_back(wire);
302 }
303
304 // Parse latches
305 RTLIL::Wire *clk_wire = nullptr;
306 if (L > 0) {
307 log_assert(clk_name != "");
308 clk_wire = module->wire(clk_name);
309 log_assert(!clk_wire);
310 log_debug("Creating %s\n", clk_name.c_str());
311 clk_wire = module->addWire(clk_name);
312 clk_wire->port_input = true;
313 clk_wire->port_output = false;
314 }
315 for (unsigned i = 0; i < L; ++i, ++line_count) {
316 if (!(f >> l1 >> l2))
317 log_error("Line %u cannot be interpreted as a latch!\n", line_count);
318 log_debug("%d %d is a latch\n", l1, l2);
319 log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted?
320 RTLIL::Wire *q_wire = createWireIfNotExists(module, l1);
321 RTLIL::Wire *d_wire = createWireIfNotExists(module, l2);
322
323 module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire);
324
325 // Reset logic is optional in AIGER 1.9
326 if (f.peek() == ' ') {
327 if (!(f >> l3))
328 log_error("Line %u cannot be interpreted as a latch!\n", line_count);
329
330 if (l3 == 0 || l3 == 1)
331 q_wire->attributes["\\init"] = RTLIL::Const(l3);
332 else if (l3 == l1) {
333 //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
334 }
335 else
336 log_error("Line %u has invalid reset literal for latch!\n", line_count);
337 }
338 else {
339 // AIGER latches are assumed to be initialized to zero
340 q_wire->attributes["\\init"] = RTLIL::Const(0);
341 }
342 latches.push_back(q_wire);
343 }
344
345 // Parse outputs
346 for (unsigned i = 0; i < O; ++i, ++line_count) {
347 if (!(f >> l1))
348 log_error("Line %u cannot be interpreted as an output!\n", line_count);
349
350 RTLIL::Wire *wire;
351 if (l1 == 0 || l1 == 1) {
352 wire = module->addWire(NEW_ID);
353 if (l1 == 0)
354 module->connect(wire, RTLIL::State::S0);
355 else if (l1 == 1)
356 module->connect(wire, RTLIL::State::S1);
357 else
358 log_abort();
359 }
360 else {
361 log_debug("%d is an output\n", l1);
362 const unsigned variable = l1 >> 1;
363 const bool invert = l1 & 1;
364 RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "b" the right suffix?
365 wire = module->wire(wire_name);
366 if (!wire)
367 wire = createWireIfNotExists(module, l1);
368 else {
369 if (wire->port_input || wire->port_output) {
370 RTLIL::Wire *new_wire = module->addWire(NEW_ID);
371 module->connect(new_wire, wire);
372 wire = new_wire;
373 }
374 }
375 }
376 wire->port_output = true;
377 outputs.push_back(wire);
378 }
379 std::getline(f, line); // Ignore up to start of next line
380
381 // TODO: Parse bad state properties
382 for (unsigned i = 0; i < B; ++i, ++line_count)
383 std::getline(f, line); // Ignore up to start of next line
384
385 // TODO: Parse invariant constraints
386 for (unsigned i = 0; i < C; ++i, ++line_count)
387 std::getline(f, line); // Ignore up to start of next line
388
389 // TODO: Parse justice properties
390 for (unsigned i = 0; i < J; ++i, ++line_count)
391 std::getline(f, line); // Ignore up to start of next line
392
393 // TODO: Parse fairness constraints
394 for (unsigned i = 0; i < F; ++i, ++line_count)
395 std::getline(f, line); // Ignore up to start of next line
396
397 // Parse AND
398 for (unsigned i = 0; i < A; ++i) {
399 if (!(f >> l1 >> l2 >> l3))
400 log_error("Line %u cannot be interpreted as an AND!\n", line_count);
401
402 log_debug("%d %d %d is an AND\n", l1, l2, l3);
403 log_assert(!(l1 & 1));
404 RTLIL::Wire *o_wire = createWireIfNotExists(module, l1);
405 RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2);
406 RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3);
407 module->addAndGate(o_wire->name.str() + "$and", i1_wire, i2_wire, o_wire);
408 }
409 std::getline(f, line); // Ignore up to start of next line
410 }
411
412 static unsigned parse_next_delta_literal(std::istream &f, unsigned ref)
413 {
414 unsigned x = 0, i = 0;
415 unsigned char ch;
416 while ((ch = f.get()) & 0x80)
417 x |= (ch & 0x7f) << (7 * i++);
418 return ref - (x | (ch << (7 * i)));
419 }
420
421 void AigerReader::parse_aiger_binary()
422 {
423 unsigned l1, l2, l3;
424 std::string line;
425
426 // Parse inputs
427 for (unsigned i = 1; i <= I; ++i) {
428 log_debug("%d is an input\n", i);
429 RTLIL::Wire *wire = createWireIfNotExists(module, i << 1);
430 wire->port_input = true;
431 log_assert(!wire->port_output);
432 inputs.push_back(wire);
433 }
434
435 // Parse latches
436 RTLIL::Wire *clk_wire = nullptr;
437 if (L > 0) {
438 log_assert(clk_name != "");
439 clk_wire = module->wire(clk_name);
440 log_assert(!clk_wire);
441 log_debug("Creating %s\n", clk_name.c_str());
442 clk_wire = module->addWire(clk_name);
443 clk_wire->port_input = true;
444 clk_wire->port_output = false;
445 }
446 l1 = (I+1) * 2;
447 for (unsigned i = 0; i < L; ++i, ++line_count, l1 += 2) {
448 if (!(f >> l2))
449 log_error("Line %u cannot be interpreted as a latch!\n", line_count);
450 log_debug("%d %d is a latch\n", l1, l2);
451 RTLIL::Wire *q_wire = createWireIfNotExists(module, l1);
452 RTLIL::Wire *d_wire = createWireIfNotExists(module, l2);
453
454 module->addDff(NEW_ID, clk_wire, d_wire, q_wire);
455
456 // Reset logic is optional in AIGER 1.9
457 if (f.peek() == ' ') {
458 if (!(f >> l3))
459 log_error("Line %u cannot be interpreted as a latch!\n", line_count);
460
461 if (l3 == 0 || l3 == 1)
462 q_wire->attributes["\\init"] = RTLIL::Const(l3);
463 else if (l3 == l1) {
464 //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
465 }
466 else
467 log_error("Line %u has invalid reset literal for latch!\n", line_count);
468 }
469 else {
470 // AIGER latches are assumed to be initialized to zero
471 q_wire->attributes["\\init"] = RTLIL::Const(0);
472 }
473 latches.push_back(q_wire);
474 }
475
476 // Parse outputs
477 for (unsigned i = 0; i < O; ++i, ++line_count) {
478 if (!(f >> l1))
479 log_error("Line %u cannot be interpreted as an output!\n", line_count);
480
481 RTLIL::Wire *wire;
482 if (l1 == 0 || l1 == 1) {
483 wire = module->addWire(NEW_ID);
484 if (l1 == 0)
485 module->connect(wire, RTLIL::State::S0);
486 else if (l1 == 1)
487 module->connect(wire, RTLIL::State::S1);
488 else
489 log_abort();
490 }
491 else {
492 log_debug("%d is an output\n", l1);
493 const unsigned variable = l1 >> 1;
494 const bool invert = l1 & 1;
495 RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "_b" the right suffix?
496 wire = module->wire(wire_name);
497 if (!wire)
498 wire = createWireIfNotExists(module, l1);
499 else {
500 if (wire->port_input || wire->port_output) {
501 RTLIL::Wire *new_wire = module->addWire(NEW_ID);
502 module->connect(new_wire, wire);
503 wire = new_wire;
504 }
505 }
506 }
507 wire->port_output = true;
508 outputs.push_back(wire);
509 }
510 std::getline(f, line); // Ignore up to start of next line
511
512 // TODO: Parse bad state properties
513 for (unsigned i = 0; i < B; ++i, ++line_count)
514 std::getline(f, line); // Ignore up to start of next line
515
516 // TODO: Parse invariant constraints
517 for (unsigned i = 0; i < C; ++i, ++line_count)
518 std::getline(f, line); // Ignore up to start of next line
519
520 // TODO: Parse justice properties
521 for (unsigned i = 0; i < J; ++i, ++line_count)
522 std::getline(f, line); // Ignore up to start of next line
523
524 // TODO: Parse fairness constraints
525 for (unsigned i = 0; i < F; ++i, ++line_count)
526 std::getline(f, line); // Ignore up to start of next line
527
528 // Parse AND
529 l1 = (I+L+1) << 1;
530 for (unsigned i = 0; i < A; ++i, ++line_count, l1 += 2) {
531 l2 = parse_next_delta_literal(f, l1);
532 l3 = parse_next_delta_literal(f, l2);
533
534 log_debug("%d %d %d is an AND\n", l1, l2, l3);
535 log_assert(!(l1 & 1));
536 RTLIL::Wire *o_wire = createWireIfNotExists(module, l1);
537 RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2);
538 RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3);
539 module->addAndGate(o_wire->name.str() + "$and", i1_wire, i2_wire, o_wire);
540 }
541 }
542
543 void AigerReader::post_process()
544 {
545 dict<RTLIL::IdString, int> wideports_cache;
546
547 if (!map_filename.empty()) {
548 std::ifstream mf(map_filename);
549 std::string type, symbol;
550 int variable, index;
551 int pi_count = 0, ci_count = 0, co_count = 0;
552 while (mf >> type >> variable >> index >> symbol) {
553 RTLIL::IdString escaped_s = RTLIL::escape_id(symbol);
554 if (type == "input") {
555 log_assert(static_cast<unsigned>(variable) < inputs.size());
556 RTLIL::Wire* wire = inputs[variable];
557 log_assert(wire);
558 log_assert(wire->port_input);
559 pi_count++;
560
561 if (index == 0) {
562 // Cope with the fact that a CI might be identical
563 // to a PI (necessary due to ABC); in those cases
564 // simply connect the latter to the former
565 RTLIL::Wire* existing = module->wire(escaped_s);
566 if (!existing)
567 module->rename(wire, escaped_s);
568 else {
569 wire->port_input = false;
570 module->connect(wire, existing);
571 }
572 }
573 else if (index > 0) {
574 std::string indexed_name = stringf("%s[%d]", escaped_s.c_str(), index);
575 RTLIL::Wire* existing = module->wire(indexed_name);
576 if (!existing) {
577 module->rename(wire, indexed_name);
578 if (wideports)
579 wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index);
580 }
581 else {
582 module->connect(wire, existing);
583 wire->port_input = false;
584 }
585 }
586 }
587 else if (type == "output") {
588 log_assert(static_cast<unsigned>(variable + co_count) < outputs.size());
589 RTLIL::Wire* wire = outputs[variable + co_count];
590 log_assert(wire);
591 log_assert(wire->port_output);
592 if (escaped_s.in("\\__dummy_o__", "\\__const0__", "\\__const1__")) {
593 wire->port_output = false;
594 continue;
595 }
596
597 if (index == 0) {
598 // Cope with the fact that a CO might be identical
599 // to a PO (necessary due to ABC); in those cases
600 // simply connect the latter to the former
601 RTLIL::Wire* existing = module->wire(escaped_s);
602 if (!existing) {
603 if (escaped_s.ends_with("$inout.out")) {
604 wire->port_output = false;
605 RTLIL::Wire *in_wire = module->wire(escaped_s.substr(0, escaped_s.size()-10));
606 log_assert(in_wire);
607 log_assert(in_wire->port_input && !in_wire->port_output);
608 in_wire->port_output = true;
609 module->connect(in_wire, wire);
610 }
611 else
612 module->rename(wire, escaped_s);
613 }
614 else {
615 wire->port_output = false;
616 module->connect(wire, existing);
617 }
618 }
619 else if (index > 0) {
620 std::string indexed_name = stringf("%s[%d]", escaped_s.c_str(), index);
621 RTLIL::Wire* existing = module->wire(indexed_name);
622 if (!existing) {
623 if (escaped_s.ends_with("$inout.out")) {
624 wire->port_output = false;
625 RTLIL::Wire *in_wire = module->wire(stringf("%s[%d]", escaped_s.substr(0, escaped_s.size()-10).c_str(), index));
626 log_assert(in_wire);
627 log_assert(in_wire->port_input && !in_wire->port_output);
628 in_wire->port_output = true;
629 module->connect(in_wire, wire);
630 }
631 else {
632 module->rename(wire, indexed_name);
633 if (wideports)
634 wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index);
635 }
636 }
637 else {
638 module->connect(wire, existing);
639 wire->port_output = false;
640 }
641 }
642 }
643 else if (type == "box") {
644 RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable));
645 if (cell) {
646 module->rename(cell, escaped_s);
647 RTLIL::Module* box_module = design->module(cell->type);
648 log_assert(box_module);
649 // NB: Assume box_module->ports are sorted alphabetically
650 // (as RTLIL::Module::fixup_ports() would do)
651 for (auto port_name : box_module->ports) {
652 RTLIL::Wire* w = box_module->wire(port_name);
653 log_assert(w);
654 RTLIL::SigSpec rhs;
655 for (int i = 0; i < GetSize(w); i++) {
656 if (w->port_input) {
657 log_assert(static_cast<unsigned>(co_count) < outputs.size());
658 RTLIL::Wire* wire = outputs[co_count++];
659 log_assert(wire);
660 log_assert(wire->port_output);
661 wire->port_output = false;
662 rhs.append(wire);
663 }
664 if (w->port_output) {
665 log_assert(static_cast<unsigned>(pi_count + ci_count) < inputs.size());
666 RTLIL::Wire* wire = inputs[pi_count + ci_count++];
667 log_assert(wire);
668 log_assert(wire->port_input);
669 wire->port_input = false;
670 rhs.append(wire);
671 }
672 }
673 cell->setPort(port_name, rhs);
674 }
675 }
676 }
677 else
678 log_error("Symbol type '%s' not recognised.\n", type.c_str());
679 }
680 }
681
682 for (auto &wp : wideports_cache) {
683 auto name = wp.first;
684 int width = wp.second + 1;
685
686 RTLIL::Wire *wire = module->wire(name);
687 if (wire)
688 module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0)));
689
690 // Do not make ports with a mix of input/output into
691 // wide ports
692 bool port_input = false, port_output = false;
693 for (int i = 0; i < width; i++) {
694 RTLIL::IdString other_name = name.str() + stringf("[%d]", i);
695 RTLIL::Wire *other_wire = module->wire(other_name);
696 if (other_wire) {
697 port_input = port_input || other_wire->port_input;
698 port_output = port_output || other_wire->port_output;
699 }
700 }
701 if ((port_input && port_output) || (!port_input && !port_output))
702 continue;
703
704 wire = module->addWire(name, width);
705 wire->port_input = port_input;
706 wire->port_output = port_output;
707
708 for (int i = 0; i < width; i++) {
709 RTLIL::IdString other_name = name.str() + stringf("[%d]", i);
710 RTLIL::Wire *other_wire = module->wire(other_name);
711 if (other_wire) {
712 other_wire->port_input = false;
713 other_wire->port_output = false;
714 if (wire->port_input)
715 module->connect(other_wire, SigSpec(wire, i));
716 else
717 module->connect(SigSpec(wire, i), other_wire);
718 }
719 }
720 }
721
722 module->fixup_ports();
723 design->add(module);
724
725 Pass::call(design, "clean");
726
727 for (auto cell : module->cells().to_vector()) {
728 if (cell->type != "$lut") continue;
729 auto y_port = cell->getPort("\\Y").as_bit();
730 if (y_port.wire->width == 1)
731 module->rename(cell, stringf("%s$lut", y_port.wire->name.c_str()));
732 else
733 module->rename(cell, stringf("%s[%d]$lut", y_port.wire->name.c_str(), y_port.offset));
734 }
735 }
736
737 struct AigerFrontend : public Frontend {
738 AigerFrontend() : Frontend("aiger", "read AIGER file") { }
739 void help() YS_OVERRIDE
740 {
741 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
742 log("\n");
743 log(" read_aiger [options] [filename]\n");
744 log("\n");
745 log("Load module from an AIGER file into the current design.\n");
746 log("\n");
747 log(" -module_name <module_name>\n");
748 log(" Name of module to be created (default: <filename>)\n");
749 log("\n");
750 log(" -clk_name <wire_name>\n");
751 log(" AIGER latches to be transformed into posedge DFFs clocked by wire of");
752 log(" this name (default: clk)\n");
753 log("\n");
754 log(" -map <filename>\n");
755 log(" read file with port and latch symbols\n");
756 log("\n");
757 log(" -wideports\n");
758 log(" Merge ports that match the pattern 'name[int]' into a single\n");
759 log(" multi-bit port 'name'.\n");
760 log("\n");
761 }
762 void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
763 {
764 log_header(design, "Executing AIGER frontend.\n");
765
766 RTLIL::IdString clk_name = "\\clk";
767 RTLIL::IdString module_name;
768 std::string map_filename;
769 bool wideports = false;
770
771 size_t argidx;
772 for (argidx = 1; argidx < args.size(); argidx++) {
773 std::string arg = args[argidx];
774 if (arg == "-module_name" && argidx+1 < args.size()) {
775 module_name = RTLIL::escape_id(args[++argidx]);
776 continue;
777 }
778 if (arg == "-clk_name" && argidx+1 < args.size()) {
779 clk_name = RTLIL::escape_id(args[++argidx]);
780 continue;
781 }
782 if (map_filename.empty() && arg == "-map" && argidx+1 < args.size()) {
783 map_filename = args[++argidx];
784 continue;
785 }
786 if (arg == "-wideports") {
787 wideports = true;
788 continue;
789 }
790 break;
791 }
792 extra_args(f, filename, args, argidx);
793
794 if (module_name.empty()) {
795 #ifdef _WIN32
796 char fname[_MAX_FNAME];
797 _splitpath(filename.c_str(), NULL /* drive */, NULL /* dir */, fname, NULL /* ext */)
798 module_name = fname;
799 #else
800 char* bn = strdup(filename.c_str());
801 module_name = RTLIL::escape_id(bn);
802 free(bn);
803 #endif
804 }
805
806 AigerReader reader(design, *f, module_name, clk_name, map_filename, wideports);
807 reader.parse_aiger();
808 }
809 } AigerFrontend;
810
811 YOSYS_NAMESPACE_END