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