4d49bb4d2674847912c753eca3a9807f8d9617b6
[yosys.git] / passes / techmap / abc9_ops.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * 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 #include "kernel/register.h"
22 #include "kernel/sigtools.h"
23 #include "kernel/utils.h"
24 #include "kernel/celltypes.h"
25
26 #define ABC9_DELAY_BASE_ID 9000
27
28 USING_YOSYS_NAMESPACE
29 PRIVATE_NAMESPACE_BEGIN
30
31 int map_autoidx;
32
33 inline std::string remap_name(RTLIL::IdString abc9_name)
34 {
35 return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1);
36 }
37
38 void check(RTLIL::Design *design)
39 {
40 dict<IdString,IdString> box_lookup;
41 for (auto m : design->modules()) {
42 auto it = m->attributes.find(ID(abc9_box_id));
43 if (it == m->attributes.end())
44 continue;
45 if (m->name.begins_with("$paramod"))
46 continue;
47 auto id = it->second.as_int();
48 auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name));
49 if (!r.second)
50 log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n",
51 log_id(m), id, log_id(r.first->second));
52
53 // Make carry in the last PI, and carry out the last PO
54 // since ABC requires it this way
55 IdString carry_in, carry_out;
56 for (const auto &port_name : m->ports) {
57 auto w = m->wire(port_name);
58 log_assert(w);
59 if (w->get_bool_attribute("\\abc9_carry")) {
60 if (w->port_input) {
61 if (carry_in != IdString())
62 log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m));
63 carry_in = port_name;
64 }
65 if (w->port_output) {
66 if (carry_out != IdString())
67 log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(m));
68 carry_out = port_name;
69 }
70 }
71 }
72
73 if (carry_in != IdString() && carry_out == IdString())
74 log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m));
75 if (carry_in == IdString() && carry_out != IdString())
76 log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m));
77 }
78 }
79
80 void break_scc(RTLIL::Module *module)
81 {
82 // For every unique SCC found, (arbitrarily) find the first
83 // cell in the component, and convert all wires driven by
84 // its output ports into a new PO, and drive its previous
85 // sinks with a new PI
86 pool<RTLIL::Const> ids_seen;
87 for (auto cell : module->selected_cells()) {
88 auto it = cell->attributes.find(ID(abc9_scc_id));
89 if (it == cell->attributes.end())
90 continue;
91 auto r = ids_seen.insert(it->second);
92 cell->attributes.erase(it);
93 if (!r.second)
94 continue;
95 for (auto &c : cell->connections_) {
96 if (c.second.is_fully_const()) continue;
97 if (cell->output(c.first)) {
98 SigBit b = c.second.as_bit();
99 Wire *w = b.wire;
100 if (w->port_input) {
101 // In this case, hopefully the loop break has been already created
102 // Get the non-prefixed wire
103 Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str()));
104 log_assert(wo != nullptr);
105 log_assert(wo->port_output);
106 log_assert(b.offset < GetSize(wo));
107 c.second = RTLIL::SigBit(wo, b.offset);
108 }
109 else {
110 // Create a new output/input loop break
111 w->port_input = true;
112 w = module->wire(stringf("%s.abco", w->name.c_str()));
113 if (!w) {
114 w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire));
115 w->port_output = true;
116 }
117 else {
118 log_assert(w->port_input);
119 log_assert(b.offset < GetSize(w));
120 }
121 w->set_bool_attribute(ID(abc9_scc_break));
122 c.second = RTLIL::SigBit(w, b.offset);
123 }
124 }
125 }
126 }
127
128 module->fixup_ports();
129 }
130
131 void unbreak_scc(RTLIL::Module *module)
132 {
133 // Now 'unexpose' those wires by undoing
134 // the expose operation -- remove them from PO/PI
135 // and re-connecting them back together
136 for (auto wire : module->wires()) {
137 auto it = wire->attributes.find(ID(abc9_scc_break));
138 if (it != wire->attributes.end()) {
139 wire->attributes.erase(it);
140 log_assert(wire->port_output);
141 wire->port_output = false;
142 std::string name = wire->name.str();
143 RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5));
144 log_assert(i_wire);
145 log_assert(i_wire->port_input);
146 i_wire->port_input = false;
147 module->connect(i_wire, wire);
148 }
149 }
150 module->fixup_ports();
151 }
152
153 void prep_dff(RTLIL::Module *module)
154 {
155 auto design = module->design;
156 log_assert(design);
157
158 SigMap assign_map(module);
159
160 typedef SigSpec clkdomain_t;
161 dict<clkdomain_t, int> clk_to_mergeability;
162
163 for (auto cell : module->selected_cells()) {
164 if (cell->type != "$__ABC9_FF_")
165 continue;
166
167 Wire *abc9_clock_wire = module->wire(stringf("%s.clock", cell->name.c_str()));
168 if (abc9_clock_wire == NULL)
169 log_error("'%s.clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
170 SigSpec abc9_clock = assign_map(abc9_clock_wire);
171
172 clkdomain_t key(abc9_clock);
173
174 auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1));
175 auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second));
176 log_assert(r2.second);
177
178 Wire *abc9_init_wire = module->wire(stringf("%s.init", cell->name.c_str()));
179 if (abc9_init_wire == NULL)
180 log_error("'%s.init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
181 log_assert(GetSize(abc9_init_wire) == 1);
182 SigSpec abc9_init = assign_map(abc9_init_wire);
183 if (!abc9_init.is_fully_const())
184 log_error("'%s.init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
185 r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const()));
186 log_assert(r2.second);
187 }
188
189 RTLIL::Module *holes_module = design->module(stringf("%s$holes", module->name.c_str()));
190 if (holes_module) {
191 dict<SigSig, SigSig> replace;
192 for (auto it = holes_module->cells_.begin(); it != holes_module->cells_.end(); ) {
193 auto cell = it->second;
194 if (cell->type.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
195 "$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_")) {
196 SigBit D = cell->getPort("\\D");
197 SigBit Q = cell->getPort("\\Q");
198 // Remove the DFF cell from what needs to be a combinatorial box
199 it = holes_module->cells_.erase(it);
200 Wire *port;
201 if (GetSize(Q.wire) == 1)
202 port = holes_module->wire(stringf("$abc%s", Q.wire->name.c_str()));
203 else
204 port = holes_module->wire(stringf("$abc%s[%d]", Q.wire->name.c_str(), Q.offset));
205 log_assert(port);
206 // Prepare to replace "assign <port> = DFF.Q;" with "assign <port> = DFF.D;"
207 // in order to extract the combinatorial control logic that feeds the box
208 // (i.e. clock enable, synchronous reset, etc.)
209 replace.insert(std::make_pair(SigSig(port,Q), SigSig(port,D)));
210 // Since `flatten` above would have created wires named "<cell>.Q",
211 // extract the pre-techmap cell name
212 auto pos = Q.wire->name.str().rfind(".");
213 log_assert(pos != std::string::npos);
214 IdString driver = Q.wire->name.substr(0, pos);
215 // And drive the signal that was previously driven by "DFF.Q" (typically
216 // used to implement clock-enable functionality) with the "<cell>.$abc9_currQ"
217 // wire (which itself is driven an input port) we inserted above
218 Wire *currQ = holes_module->wire(stringf("%s.abc9_ff.Q", driver.c_str()));
219 log_assert(currQ);
220 holes_module->connect(Q, currQ);
221 }
222 else
223 ++it;
224 }
225
226 for (auto &conn : holes_module->connections_) {
227 auto it = replace.find(conn);
228 if (it != replace.end())
229 conn = it->second;
230 }
231 }
232 }
233
234 void prep_holes(RTLIL::Module *module, bool dff)
235 {
236 auto design = module->design;
237 log_assert(design);
238
239 SigMap sigmap(module);
240
241 dict<SigBit, pool<IdString>> bit_drivers, bit_users;
242 TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
243 bool abc9_box_seen = false;
244
245 for (auto cell : module->selected_cells()) {
246 if (cell->type == "$__ABC9_FF_")
247 continue;
248
249 auto inst_module = module->design->module(cell->type);
250 bool abc9_box = inst_module && inst_module->attributes.count("\\abc9_box_id");
251 bool abc9_flop = false;
252 if (abc9_box) {
253 abc9_flop = inst_module->get_bool_attribute("\\abc9_flop");
254 if (abc9_flop && !dff)
255 continue;
256 abc9_box_seen = abc9_box;
257 }
258 else if (!yosys_celltypes.cell_known(cell->type))
259 continue;
260
261 for (auto conn : cell->connections()) {
262 if (cell->input(conn.first))
263 for (auto bit : sigmap(conn.second))
264 bit_users[bit].insert(cell->name);
265
266 if (cell->output(conn.first) && !abc9_flop)
267 for (auto bit : sigmap(conn.second))
268 bit_drivers[bit].insert(cell->name);
269 }
270
271 toposort.node(cell->name);
272 }
273
274 if (!abc9_box_seen)
275 return;
276
277 for (auto &it : bit_users)
278 if (bit_drivers.count(it.first))
279 for (auto driver_cell : bit_drivers.at(it.first))
280 for (auto user_cell : it.second)
281 toposort.edge(driver_cell, user_cell);
282
283 #if 0
284 toposort.analyze_loops = true;
285 #endif
286 bool no_loops YS_ATTRIBUTE(unused) = toposort.sort();
287 #if 0
288 unsigned i = 0;
289 for (auto &it : toposort.loops) {
290 log(" loop %d\n", i++);
291 for (auto cell_name : it) {
292 auto cell = module->cell(cell_name);
293 log_assert(cell);
294 log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute().c_str());
295 }
296 }
297 #endif
298 log_assert(no_loops);
299
300 vector<Cell*> box_list;
301 for (auto cell_name : toposort.sorted) {
302 RTLIL::Cell *cell = module->cell(cell_name);
303 log_assert(cell);
304
305 RTLIL::Module* box_module = design->module(cell->type);
306 if (!box_module || !box_module->attributes.count("\\abc9_box_id"))
307 continue;
308
309 bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */);
310
311 // Fully pad all unused input connections of this box cell with S0
312 // Fully pad all undriven output connections of this box cell with anonymous wires
313 for (const auto &port_name : box_module->ports) {
314 RTLIL::Wire* w = box_module->wire(port_name);
315 log_assert(w);
316 auto it = cell->connections_.find(port_name);
317 if (w->port_input) {
318 RTLIL::SigSpec rhs;
319 if (it != cell->connections_.end()) {
320 if (GetSize(it->second) < GetSize(w))
321 it->second.append(RTLIL::SigSpec(State::S0, GetSize(w)-GetSize(it->second)));
322 rhs = it->second;
323 }
324 else {
325 rhs = RTLIL::SigSpec(State::S0, GetSize(w));
326 cell->setPort(port_name, rhs);
327 }
328 }
329 if (w->port_output) {
330 RTLIL::SigSpec rhs;
331 auto it = cell->connections_.find(w->name);
332 if (it != cell->connections_.end()) {
333 if (GetSize(it->second) < GetSize(w))
334 it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second)));
335 rhs = it->second;
336 }
337 else {
338 Wire *wire = module->addWire(NEW_ID, GetSize(w));
339 if (blackbox)
340 wire->set_bool_attribute(ID(abc9_padding));
341 rhs = wire;
342 cell->setPort(port_name, rhs);
343 }
344 }
345 }
346
347 cell->attributes["\\abc9_box_seq"] = box_list.size();
348 //log_debug("%s.%s is box %d\n", log_id(module), log_id(cell), box_list.size());
349 box_list.emplace_back(cell);
350 }
351 log_assert(!box_list.empty());
352
353 RTLIL::Module *holes_module = design->addModule(stringf("%s$holes", module->name.c_str()));
354 log_assert(holes_module);
355 holes_module->set_bool_attribute("\\abc9_holes");
356
357 dict<IdString, Cell*> cell_cache;
358 dict<IdString, std::vector<IdString>> box_ports;
359
360 int port_id = 1;
361 for (auto cell : box_list) {
362 RTLIL::Module* orig_box_module = design->module(cell->type);
363 log_assert(orig_box_module);
364 IdString derived_name = orig_box_module->derive(design, cell->parameters);
365 RTLIL::Module* box_module = design->module(derived_name);
366 cell->type = derived_name;
367 cell->parameters.clear();
368
369 int box_inputs = 0;
370 auto r = cell_cache.insert(std::make_pair(derived_name, nullptr));
371 Cell *holes_cell = r.first->second;
372 if (r.second && box_module->get_bool_attribute("\\whitebox")) {
373 holes_cell = holes_module->addCell(cell->name, cell->type);
374 holes_cell->parameters = cell->parameters;
375 r.first->second = holes_cell;
376
377 if (box_module->has_processes())
378 Pass::call_on_module(design, box_module, "proc");
379 }
380
381 auto r2 = box_ports.insert(cell->type);
382 if (r2.second) {
383 // Make carry in the last PI, and carry out the last PO
384 // since ABC requires it this way
385 IdString carry_in, carry_out;
386 for (const auto &port_name : box_module->ports) {
387 auto w = box_module->wire(port_name);
388 log_assert(w);
389 if (w->get_bool_attribute("\\abc9_carry")) {
390 if (w->port_input)
391 carry_in = port_name;
392 if (w->port_output)
393 carry_out = port_name;
394 }
395 else
396 r2.first->second.push_back(port_name);
397 }
398
399 if (carry_in != IdString()) {
400 r2.first->second.push_back(carry_in);
401 r2.first->second.push_back(carry_out);
402 }
403 }
404
405 for (const auto &port_name : box_ports.at(cell->type)) {
406 RTLIL::Wire *w = box_module->wire(port_name);
407 log_assert(w);
408 RTLIL::Wire *holes_wire;
409 RTLIL::SigSpec port_sig;
410 if (w->port_input)
411 for (int i = 0; i < GetSize(w); i++) {
412 box_inputs++;
413 holes_wire = holes_module->wire(stringf("\\i%d", box_inputs));
414 if (!holes_wire) {
415 holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs));
416 holes_wire->port_input = true;
417 holes_wire->port_id = port_id++;
418 holes_module->ports.push_back(holes_wire->name);
419 }
420 if (holes_cell)
421 port_sig.append(holes_wire);
422 }
423 if (w->port_output)
424 for (int i = 0; i < GetSize(w); i++) {
425 if (GetSize(w) == 1)
426 holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name.c_str(), log_id(w->name)));
427 else
428 holes_wire = holes_module->addWire(stringf("$abc%s.%s[%d]", cell->name.c_str(), log_id(w->name), i));
429 holes_wire->port_output = true;
430 holes_wire->port_id = port_id++;
431 holes_module->ports.push_back(holes_wire->name);
432 if (holes_cell)
433 port_sig.append(holes_wire);
434 else
435 holes_module->connect(holes_wire, State::S0);
436 }
437 if (!port_sig.empty()) {
438 if (r.second)
439 holes_cell->setPort(w->name, port_sig);
440 else
441 holes_module->connect(holes_cell->getPort(w->name), port_sig);
442 }
443 }
444
445 // For flops only, create an extra 1-bit input that drives a new wire
446 // called "<cell>.$abc9_currQ" that is used below
447 if (box_module->get_bool_attribute("\\abc9_flop")) {
448 log_assert(holes_cell);
449
450 box_inputs++;
451 Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs));
452 if (!holes_wire) {
453 holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs));
454 holes_wire->port_input = true;
455 holes_wire->port_id = port_id++;
456 holes_module->ports.push_back(holes_wire->name);
457 }
458 Wire *w = holes_module->addWire(stringf("%s.abc9_ff.Q", cell->name.c_str()));
459 holes_module->connect(w, holes_wire);
460 }
461 }
462 }
463
464 void prep_times(RTLIL::Design *design)
465 {
466 std::set<int> delays;
467 std::vector<Cell*> boxes;
468 std::map<int,std::vector<int>> requireds;
469 for (auto module : design->selected_modules()) {
470 if (module->get_bool_attribute("\\abc9_holes"))
471 continue;
472
473 if (module->processes.size() > 0) {
474 log("Skipping module %s as it contains processes.\n", log_id(module));
475 continue;
476 }
477
478 boxes.clear();
479 for (auto cell : module->cells()) {
480 if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_), ID($__ABC9_DELAY)))
481 continue;
482
483 RTLIL::Module* inst_module = module->design->module(cell->type);
484 if (!inst_module)
485 continue;
486 if (!inst_module->get_blackbox_attribute())
487 continue;
488 // Flop inputs cannot have required times
489 // (required time should be captured by flop box)
490 // TODO: enforce this
491 if (cell->attributes.count(ID(abc9_box_id)))
492 continue;
493 boxes.emplace_back(cell);
494 }
495
496 delays.clear();
497 requireds.clear();
498 for (auto cell : boxes) {
499 RTLIL::Module* inst_module = module->design->module(cell->type);
500
501 for (auto &conn : cell->connections_) {
502 auto port_wire = inst_module->wire(conn.first);
503 if (!port_wire->port_input)
504 continue;
505
506 auto it = port_wire->attributes.find("\\abc9_required");
507 if (it == port_wire->attributes.end())
508 continue;
509
510 int count = 0;
511 requireds.clear();
512 if (it->second.flags == 0) {
513 count = 1;
514 requireds[it->second.as_int()].push_back(0);
515 }
516 else
517 for (const auto &tok : split_tokens(it->second.decode_string()))
518 requireds[atoi(tok.c_str())].push_back(count++);
519 if (count > 1 && count != GetSize(port_wire))
520 log_error("%s.%s is %d bits wide but abc9_required = %s has %d value(s)!\n", log_id(cell->type), log_id(conn.first),
521 GetSize(port_wire), log_signal(it->second), count);
522
523 SigSpec O = module->addWire(NEW_ID, GetSize(conn.second));
524 for (const auto &i : requireds) {
525 delays.insert(i.first);
526 for (auto offset : i.second) {
527 auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY));
528 box->setPort(ID(I), conn.second[offset]);
529 box->setPort(ID(O), O[offset]);
530 box->setParam(ID(DELAY), i.first);
531 conn.second[offset] = O[offset];
532 }
533 }
534 }
535 }
536
537 std::stringstream ss;
538 bool first = true;
539 for (auto d : delays)
540 if (first) {
541 first = false;
542 ss << d;
543 }
544 else
545 ss << " " << d;
546 module->attributes[ID(abc9_delays)] = ss.str();
547 }
548 }
549
550 void write_box(RTLIL::Module *module, const std::string &src, const std::string &dst) {
551 std::ofstream ofs(dst);
552 log_assert(ofs.is_open());
553
554 // Since ABC can only accept one box file, we have to copy
555 // over the existing box file
556 if (src != "(null)") {
557 std::ifstream ifs(src);
558 ofs << ifs.rdbuf() << std::endl;
559 ifs.close();
560 }
561
562 auto it = module->attributes.find(ID(abc9_delays));
563 if (it != module->attributes.end()) {
564 for (const auto &tok : split_tokens(it->second.decode_string())) {
565 int d = atoi(tok.c_str());
566 ofs << "$__ABC9_DELAY@" << d << " " << ABC9_DELAY_BASE_ID + d << " 0 1 1" << std::endl;
567 ofs << d << std::endl;
568 }
569 }
570
571 ofs.close();
572 }
573
574 void reintegrate(RTLIL::Module *module)
575 {
576 auto design = module->design;
577 log_assert(design);
578
579 map_autoidx = autoidx++;
580
581 RTLIL::Module *mapped_mod = design->module(stringf("%s$abc9", module->name.c_str()));
582 if (mapped_mod == NULL)
583 log_error("ABC output file does not contain a module `%s$abc'.\n", log_id(module));
584
585 for (auto w : mapped_mod->wires())
586 module->addWire(remap_name(w->name), GetSize(w));
587
588 dict<IdString,IdString> box_lookup;
589 for (auto m : design->modules()) {
590 auto it = m->attributes.find(ID(abc9_box_id));
591 if (it == m->attributes.end())
592 continue;
593 if (m->name.begins_with("$paramod"))
594 continue;
595 auto id = it->second.as_int();
596 auto r YS_ATTRIBUTE(unused) = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name));
597 log_assert(r.second);
598 }
599
600 pool<IdString> delay_boxes;
601 std::vector<Cell*> boxes;
602 for (auto cell : module->cells().to_vector()) {
603 if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_)))
604 module->remove(cell);
605 else if (cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) {
606 delay_boxes.insert(cell->name);
607 module->remove(cell);
608 }
609 else if (cell->attributes.erase("\\abc9_box_seq"))
610 boxes.emplace_back(cell);
611 }
612
613 dict<SigBit, pool<IdString>> bit_drivers, bit_users;
614 TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
615 dict<RTLIL::Cell*,RTLIL::Cell*> not2drivers;
616 dict<SigBit, std::vector<RTLIL::Cell*>> bit2sinks;
617
618 dict<IdString,std::vector<IdString>> box_ports;
619 std::map<IdString, int> cell_stats;
620 for (auto mapped_cell : mapped_mod->cells())
621 {
622 toposort.node(mapped_cell->name);
623
624 if (mapped_cell->type == ID($_NOT_)) {
625 RTLIL::SigBit a_bit = mapped_cell->getPort(ID::A);
626 RTLIL::SigBit y_bit = mapped_cell->getPort(ID::Y);
627 bit_users[a_bit].insert(mapped_cell->name);
628 bit_drivers[y_bit].insert(mapped_cell->name);
629
630 if (!a_bit.wire) {
631 mapped_cell->setPort(ID::Y, module->addWire(NEW_ID));
632 RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name));
633 log_assert(wire);
634 module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1);
635 }
636 else {
637 RTLIL::Cell* driver_lut = nullptr;
638 // ABC can return NOT gates that drive POs
639 if (!a_bit.wire->port_input) {
640 // If it's not a NOT gate that that comes from a PI directly,
641 // find the driver LUT and clone that to guarantee that we won't
642 // increase the max logic depth
643 // (TODO: Optimise by not cloning unless will increase depth)
644 RTLIL::IdString driver_name;
645 if (GetSize(a_bit.wire) == 1)
646 driver_name = stringf("%s$lut", a_bit.wire->name.c_str());
647 else
648 driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset);
649 driver_lut = mapped_mod->cell(driver_name);
650 }
651
652 if (!driver_lut) {
653 // If a driver couldn't be found (could be from PI or box CI)
654 // then implement using a LUT
655 RTLIL::Cell *cell = module->addLut(remap_name(stringf("%s$lut", mapped_cell->name.c_str())),
656 RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset),
657 RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset),
658 RTLIL::Const::from_string("01"));
659 bit2sinks[cell->getPort(ID::A)].push_back(cell);
660 cell_stats[ID($lut)]++;
661 }
662 else
663 not2drivers[mapped_cell] = driver_lut;
664 }
665 continue;
666 }
667
668 if (mapped_cell->type.in(ID($lut), ID($__ABC9_FF_))) {
669 RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
670 cell->parameters = mapped_cell->parameters;
671 cell->attributes = mapped_cell->attributes;
672
673 for (auto &mapped_conn : mapped_cell->connections()) {
674 RTLIL::SigSpec newsig;
675 for (auto c : mapped_conn.second.chunks()) {
676 if (c.width == 0)
677 continue;
678 //log_assert(c.width == 1);
679 if (c.wire)
680 c.wire = module->wires_.at(remap_name(c.wire->name));
681 newsig.append(c);
682 }
683 cell->setPort(mapped_conn.first, newsig);
684
685 if (cell->input(mapped_conn.first)) {
686 for (auto i : newsig)
687 bit2sinks[i].push_back(cell);
688 for (auto i : mapped_conn.second)
689 bit_users[i].insert(mapped_cell->name);
690 }
691 if (cell->output(mapped_conn.first))
692 for (auto i : mapped_conn.second)
693 bit_drivers[i].insert(mapped_cell->name);
694 }
695 }
696 else if (delay_boxes.count(mapped_cell->name)) {
697 SigBit I = mapped_cell->getPort(ID(i));
698 SigBit O = mapped_cell->getPort(ID(o));
699 if (I.wire)
700 I.wire = module->wires_.at(remap_name(I.wire->name));
701 log_assert(O.wire);
702 O.wire = module->wires_.at(remap_name(O.wire->name));
703 module->connect(O, I);
704 continue;
705 }
706 else {
707 RTLIL::Cell *existing_cell = module->cell(mapped_cell->name);
708 log_assert(existing_cell);
709 log_assert(mapped_cell->type.begins_with("$__boxid"));
710
711 auto type = box_lookup.at(mapped_cell->type, IdString());
712 if (type == IdString())
713 log_error("No module with abc9_box_id = %s found.\n", mapped_cell->type.c_str() + strlen("$__boxid"));
714 mapped_cell->type = type;
715
716 RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
717 cell->parameters = existing_cell->parameters;
718 cell->attributes = existing_cell->attributes;
719 module->swap_names(cell, existing_cell);
720
721 auto it = mapped_cell->connections_.find("\\i");
722 log_assert(it != mapped_cell->connections_.end());
723 SigSpec inputs = std::move(it->second);
724 mapped_cell->connections_.erase(it);
725 it = mapped_cell->connections_.find("\\o");
726 log_assert(it != mapped_cell->connections_.end());
727 SigSpec outputs = std::move(it->second);
728 mapped_cell->connections_.erase(it);
729
730 RTLIL::Module* box_module = design->module(mapped_cell->type);
731 auto abc9_flop = box_module->attributes.count("\\abc9_flop");
732 if (!abc9_flop) {
733 for (const auto &i : inputs)
734 bit_users[i].insert(mapped_cell->name);
735 for (const auto &i : outputs)
736 bit_drivers[i].insert(mapped_cell->name);
737 }
738
739 auto r2 = box_ports.insert(cell->type);
740 if (r2.second) {
741 // Make carry in the last PI, and carry out the last PO
742 // since ABC requires it this way
743 IdString carry_in, carry_out;
744 for (const auto &port_name : box_module->ports) {
745 auto w = box_module->wire(port_name);
746 log_assert(w);
747 if (w->get_bool_attribute("\\abc9_carry")) {
748 if (w->port_input)
749 carry_in = port_name;
750 if (w->port_output)
751 carry_out = port_name;
752 }
753 else
754 r2.first->second.push_back(port_name);
755 }
756
757 if (carry_in != IdString()) {
758 r2.first->second.push_back(carry_in);
759 r2.first->second.push_back(carry_out);
760 }
761 }
762
763 int input_count = 0, output_count = 0;
764 for (const auto &port_name : box_ports.at(cell->type)) {
765 RTLIL::Wire *w = box_module->wire(port_name);
766 log_assert(w);
767
768 SigSpec sig;
769 if (w->port_input) {
770 sig = inputs.extract(input_count, GetSize(w));
771 input_count += GetSize(w);
772 }
773 if (w->port_output) {
774 sig = outputs.extract(output_count, GetSize(w));
775 output_count += GetSize(w);
776 }
777
778 SigSpec newsig;
779 for (auto c : sig.chunks()) {
780 if (c.width == 0)
781 continue;
782 //log_assert(c.width == 1);
783 if (c.wire)
784 c.wire = module->wires_.at(remap_name(c.wire->name));
785 newsig.append(c);
786 }
787
788 auto it = existing_cell->connections_.find(port_name);
789 if (it == existing_cell->connections_.end())
790 continue;
791 if (GetSize(newsig) > GetSize(it->second))
792 newsig = newsig.extract(0, GetSize(it->second));
793 else
794 log_assert(GetSize(newsig) == GetSize(it->second));
795
796 cell->setPort(port_name, newsig);
797
798 if (w->port_input && !abc9_flop)
799 for (const auto &i : newsig)
800 bit2sinks[i].push_back(cell);
801 }
802 }
803
804 cell_stats[mapped_cell->type]++;
805 }
806
807 for (auto cell : boxes)
808 module->remove(cell);
809
810 // Copy connections (and rename) from mapped_mod to module
811 for (auto conn : mapped_mod->connections()) {
812 if (!conn.first.is_fully_const()) {
813 auto chunks = conn.first.chunks();
814 for (auto &c : chunks)
815 c.wire = module->wires_.at(remap_name(c.wire->name));
816 conn.first = std::move(chunks);
817 }
818 if (!conn.second.is_fully_const()) {
819 auto chunks = conn.second.chunks();
820 for (auto &c : chunks)
821 if (c.wire)
822 c.wire = module->wires_.at(remap_name(c.wire->name));
823 conn.second = std::move(chunks);
824 }
825 module->connect(conn);
826 }
827
828 for (auto &it : cell_stats)
829 log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second);
830 int in_wires = 0, out_wires = 0;
831
832 // Stitch in mapped_mod's inputs/outputs into module
833 for (auto port : mapped_mod->ports) {
834 RTLIL::Wire *w = mapped_mod->wire(port);
835 RTLIL::Wire *wire = module->wire(port);
836 log_assert(wire);
837 RTLIL::Wire *remap_wire = module->wire(remap_name(port));
838 RTLIL::SigSpec signal(wire, 0, GetSize(remap_wire));
839 log_assert(GetSize(signal) >= GetSize(remap_wire));
840
841 RTLIL::SigSig conn;
842 if (w->port_output) {
843 conn.first = signal;
844 conn.second = remap_wire;
845 out_wires++;
846 module->connect(conn);
847 }
848 else if (w->port_input) {
849 conn.first = remap_wire;
850 conn.second = signal;
851 in_wires++;
852 module->connect(conn);
853 }
854 }
855
856 for (auto &it : bit_users)
857 if (bit_drivers.count(it.first))
858 for (auto driver_cell : bit_drivers.at(it.first))
859 for (auto user_cell : it.second)
860 toposort.edge(driver_cell, user_cell);
861 bool no_loops YS_ATTRIBUTE(unused) = toposort.sort();
862 log_assert(no_loops);
863
864 for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) {
865 RTLIL::Cell *not_cell = mapped_mod->cell(*ii);
866 log_assert(not_cell);
867 if (not_cell->type != ID($_NOT_))
868 continue;
869 auto it = not2drivers.find(not_cell);
870 if (it == not2drivers.end())
871 continue;
872 RTLIL::Cell *driver_lut = it->second;
873 RTLIL::SigBit a_bit = not_cell->getPort(ID::A);
874 RTLIL::SigBit y_bit = not_cell->getPort(ID::Y);
875 RTLIL::Const driver_mask;
876
877 a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name));
878 y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name));
879
880 auto jt = bit2sinks.find(a_bit);
881 if (jt == bit2sinks.end())
882 goto clone_lut;
883
884 for (auto sink_cell : jt->second)
885 if (sink_cell->type != ID($lut))
886 goto clone_lut;
887
888 // Push downstream LUTs past inverter
889 for (auto sink_cell : jt->second) {
890 SigSpec A = sink_cell->getPort(ID::A);
891 RTLIL::Const mask = sink_cell->getParam(ID(LUT));
892 int index = 0;
893 for (; index < GetSize(A); index++)
894 if (A[index] == a_bit)
895 break;
896 log_assert(index < GetSize(A));
897 int i = 0;
898 while (i < GetSize(mask)) {
899 for (int j = 0; j < (1 << index); j++)
900 std::swap(mask[i+j], mask[i+j+(1 << index)]);
901 i += 1 << (index+1);
902 }
903 A[index] = y_bit;
904 sink_cell->setPort(ID::A, A);
905 sink_cell->setParam(ID(LUT), mask);
906 }
907
908 // Since we have rewritten all sinks (which we know
909 // to be only LUTs) to be after the inverter, we can
910 // go ahead and clone the LUT with the expectation
911 // that the original driving LUT will become dangling
912 // and get cleaned away
913 clone_lut:
914 driver_mask = driver_lut->getParam(ID(LUT));
915 for (auto &b : driver_mask.bits) {
916 if (b == RTLIL::State::S0) b = RTLIL::State::S1;
917 else if (b == RTLIL::State::S1) b = RTLIL::State::S0;
918 }
919 auto cell = module->addLut(NEW_ID,
920 driver_lut->getPort(ID::A),
921 y_bit,
922 driver_mask);
923 for (auto &bit : cell->connections_.at(ID::A)) {
924 bit.wire = module->wires_.at(remap_name(bit.wire->name));
925 bit2sinks[bit].push_back(cell);
926 }
927 }
928
929 //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires);
930 log("ABC RESULTS: input signals: %8d\n", in_wires);
931 log("ABC RESULTS: output signals: %8d\n", out_wires);
932
933 design->remove(mapped_mod);
934 }
935
936 struct Abc9OpsPass : public Pass {
937 Abc9OpsPass() : Pass("abc9_ops", "helper functions for ABC9") { }
938 void help() YS_OVERRIDE
939 {
940 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
941 log("\n");
942 log(" abc9_ops [options] [selection]\n");
943 log("\n");
944 }
945 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
946 {
947 log_header(design, "Executing ABC9_OPS pass (helper functions for ABC9).\n");
948
949 bool check_mode = false;
950 bool prep_times_mode = false;
951 bool break_scc_mode = false;
952 bool unbreak_scc_mode = false;
953 bool prep_holes_mode = false;
954 bool prep_dff_mode = false;
955 std::string write_box_src, write_box_dst;
956 bool reintegrate_mode = false;
957 bool dff_mode = false;
958
959 size_t argidx;
960 for (argidx = 1; argidx < args.size(); argidx++) {
961 std::string arg = args[argidx];
962 if (arg == "-check") {
963 check_mode = true;
964 continue;
965 }
966 if (arg == "-break_scc") {
967 break_scc_mode = true;
968 continue;
969 }
970 if (arg == "-unbreak_scc") {
971 unbreak_scc_mode = true;
972 continue;
973 }
974 if (arg == "-prep_dff") {
975 prep_dff_mode = true;
976 continue;
977 }
978 if (arg == "-prep_holes") {
979 prep_holes_mode = true;
980 continue;
981 }
982 if (arg == "-prep_times") {
983 prep_times_mode = true;
984 continue;
985 }
986 if (arg == "-write_box" && argidx+2 < args.size()) {
987 write_box_src = args[++argidx];
988 write_box_dst = args[++argidx];
989 rewrite_filename(write_box_src);
990 rewrite_filename(write_box_dst);
991 continue;
992 }
993 if (arg == "-reintegrate") {
994 reintegrate_mode = true;
995 continue;
996 }
997 if (arg == "-dff") {
998 dff_mode = true;
999 continue;
1000 }
1001 break;
1002 }
1003 extra_args(args, argidx, design);
1004
1005 // TODO: Check at least one mode given
1006
1007 if (check_mode)
1008 check(design);
1009 if (prep_times_mode)
1010 prep_times(design);
1011
1012 for (auto mod : design->selected_modules()) {
1013 if (mod->get_bool_attribute("\\abc9_holes"))
1014 continue;
1015
1016 if (mod->processes.size() > 0) {
1017 log("Skipping module %s as it contains processes.\n", log_id(mod));
1018 continue;
1019 }
1020
1021 if (break_scc_mode)
1022 break_scc(mod);
1023 if (unbreak_scc_mode)
1024 unbreak_scc(mod);
1025 if (prep_holes_mode)
1026 prep_holes(mod, dff_mode);
1027 if (prep_dff_mode)
1028 prep_dff(mod);
1029 if (!write_box_src.empty())
1030 write_box(mod, write_box_src, write_box_dst);
1031 if (reintegrate_mode)
1032 reintegrate(mod);
1033 }
1034 }
1035 } Abc9OpsPass;
1036
1037 PRIVATE_NAMESPACE_END