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