816c0276a4d19b6196a9d8783672f2ba5ab818a6
[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_delays(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 (box_lookup.at(mapped_cell->type, IdString()) == 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 if (!existing_cell)
675 log_error("Cannot find existing box cell with name '%s' in original design.\n", log_id(mapped_cell));
676 log_assert(mapped_cell->type.begins_with("$__boxid"));
677
678 auto type = box_lookup.at(mapped_cell->type, IdString());
679 if (type == IdString())
680 log_error("No module with abc9_box_id = %s found.\n", mapped_cell->type.c_str() + strlen("$__boxid"));
681 mapped_cell->type = type;
682
683 RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
684 cell->parameters = existing_cell->parameters;
685 cell->attributes = existing_cell->attributes;
686 module->swap_names(cell, existing_cell);
687
688 auto it = mapped_cell->connections_.find("\\i");
689 log_assert(it != mapped_cell->connections_.end());
690 SigSpec inputs = std::move(it->second);
691 mapped_cell->connections_.erase(it);
692 it = mapped_cell->connections_.find("\\o");
693 log_assert(it != mapped_cell->connections_.end());
694 SigSpec outputs = std::move(it->second);
695 mapped_cell->connections_.erase(it);
696
697 RTLIL::Module* box_module = design->module(mapped_cell->type);
698 auto abc9_flop = box_module->attributes.count("\\abc9_flop");
699 if (!abc9_flop) {
700 for (const auto &i : inputs)
701 bit_users[i].insert(mapped_cell->name);
702 for (const auto &i : outputs)
703 // Ignore inouts for topo ordering
704 if (i.wire && !(i.wire->port_input && i.wire->port_output))
705 bit_drivers[i].insert(mapped_cell->name);
706 }
707
708 auto r2 = box_ports.insert(cell->type);
709 if (r2.second) {
710 // Make carry in the last PI, and carry out the last PO
711 // since ABC requires it this way
712 IdString carry_in, carry_out;
713 for (const auto &port_name : box_module->ports) {
714 auto w = box_module->wire(port_name);
715 log_assert(w);
716 if (w->get_bool_attribute("\\abc9_carry")) {
717 log_assert(w->port_input != w->port_output);
718 if (w->port_input)
719 carry_in = port_name;
720 else if (w->port_output)
721 carry_out = port_name;
722 }
723 else
724 r2.first->second.push_back(port_name);
725 }
726
727 if (carry_in != IdString()) {
728 r2.first->second.push_back(carry_in);
729 r2.first->second.push_back(carry_out);
730 }
731 }
732
733 int input_count = 0, output_count = 0;
734 for (const auto &port_name : box_ports.at(cell->type)) {
735 RTLIL::Wire *w = box_module->wire(port_name);
736 log_assert(w);
737
738 SigSpec sig;
739 if (w->port_input) {
740 sig = inputs.extract(input_count, GetSize(w));
741 input_count += GetSize(w);
742 }
743 if (w->port_output) {
744 sig = outputs.extract(output_count, GetSize(w));
745 output_count += GetSize(w);
746 }
747
748 SigSpec newsig;
749 for (auto c : sig.chunks()) {
750 if (c.width == 0)
751 continue;
752 //log_assert(c.width == 1);
753 if (c.wire)
754 c.wire = module->wires_.at(remap_name(c.wire->name));
755 newsig.append(c);
756 }
757
758 auto it = existing_cell->connections_.find(port_name);
759 if (it == existing_cell->connections_.end())
760 continue;
761 if (GetSize(newsig) > GetSize(it->second))
762 newsig = newsig.extract(0, GetSize(it->second));
763 else
764 log_assert(GetSize(newsig) == GetSize(it->second));
765
766 cell->setPort(port_name, newsig);
767
768 if (w->port_input && !abc9_flop)
769 for (const auto &i : newsig)
770 bit2sinks[i].push_back(cell);
771 }
772 }
773
774 cell_stats[mapped_cell->type]++;
775 }
776
777 for (auto cell : boxes)
778 module->remove(cell);
779
780 // Copy connections (and rename) from mapped_mod to module
781 for (auto conn : mapped_mod->connections()) {
782 if (!conn.first.is_fully_const()) {
783 auto chunks = conn.first.chunks();
784 for (auto &c : chunks)
785 c.wire = module->wires_.at(remap_name(c.wire->name));
786 conn.first = std::move(chunks);
787 }
788 if (!conn.second.is_fully_const()) {
789 auto chunks = conn.second.chunks();
790 for (auto &c : chunks)
791 if (c.wire)
792 c.wire = module->wires_.at(remap_name(c.wire->name));
793 conn.second = std::move(chunks);
794 }
795 module->connect(conn);
796 }
797
798 for (auto &it : cell_stats)
799 log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second);
800 int in_wires = 0, out_wires = 0;
801
802 // Stitch in mapped_mod's inputs/outputs into module
803 for (auto port : mapped_mod->ports) {
804 RTLIL::Wire *mapped_wire = mapped_mod->wire(port);
805 RTLIL::Wire *wire = module->wire(port);
806 log_assert(wire);
807 if (wire->attributes.erase(ID(abc9_scc_id))) {
808 auto r YS_ATTRIBUTE(unused) = wire->attributes.erase(ID::keep);
809 log_assert(r);
810 }
811 RTLIL::Wire *remap_wire = module->wire(remap_name(port));
812 RTLIL::SigSpec signal(wire, 0, GetSize(remap_wire));
813 log_assert(GetSize(signal) >= GetSize(remap_wire));
814
815 RTLIL::SigSig conn;
816 if (mapped_wire->port_output) {
817 conn.first = signal;
818 conn.second = remap_wire;
819 out_wires++;
820 module->connect(conn);
821 }
822 else if (mapped_wire->port_input) {
823 conn.first = remap_wire;
824 conn.second = signal;
825 in_wires++;
826 module->connect(conn);
827 }
828 }
829
830 for (auto &it : bit_users)
831 if (bit_drivers.count(it.first))
832 for (auto driver_cell : bit_drivers.at(it.first))
833 for (auto user_cell : it.second)
834 toposort.edge(driver_cell, user_cell);
835 bool no_loops YS_ATTRIBUTE(unused) = toposort.sort();
836 log_assert(no_loops);
837
838 for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) {
839 RTLIL::Cell *not_cell = mapped_mod->cell(*ii);
840 log_assert(not_cell);
841 if (not_cell->type != ID($_NOT_))
842 continue;
843 auto it = not2drivers.find(not_cell);
844 if (it == not2drivers.end())
845 continue;
846 RTLIL::Cell *driver_lut = it->second;
847 RTLIL::SigBit a_bit = not_cell->getPort(ID::A);
848 RTLIL::SigBit y_bit = not_cell->getPort(ID::Y);
849 RTLIL::Const driver_mask;
850
851 a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name));
852 y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name));
853
854 auto jt = bit2sinks.find(a_bit);
855 if (jt == bit2sinks.end())
856 goto clone_lut;
857
858 for (auto sink_cell : jt->second)
859 if (sink_cell->type != ID($lut))
860 goto clone_lut;
861
862 // Push downstream LUTs past inverter
863 for (auto sink_cell : jt->second) {
864 SigSpec A = sink_cell->getPort(ID::A);
865 RTLIL::Const mask = sink_cell->getParam(ID(LUT));
866 int index = 0;
867 for (; index < GetSize(A); index++)
868 if (A[index] == a_bit)
869 break;
870 log_assert(index < GetSize(A));
871 int i = 0;
872 while (i < GetSize(mask)) {
873 for (int j = 0; j < (1 << index); j++)
874 std::swap(mask[i+j], mask[i+j+(1 << index)]);
875 i += 1 << (index+1);
876 }
877 A[index] = y_bit;
878 sink_cell->setPort(ID::A, A);
879 sink_cell->setParam(ID(LUT), mask);
880 }
881
882 // Since we have rewritten all sinks (which we know
883 // to be only LUTs) to be after the inverter, we can
884 // go ahead and clone the LUT with the expectation
885 // that the original driving LUT will become dangling
886 // and get cleaned away
887 clone_lut:
888 driver_mask = driver_lut->getParam(ID(LUT));
889 for (auto &b : driver_mask.bits) {
890 if (b == RTLIL::State::S0) b = RTLIL::State::S1;
891 else if (b == RTLIL::State::S1) b = RTLIL::State::S0;
892 }
893 auto cell = module->addLut(NEW_ID,
894 driver_lut->getPort(ID::A),
895 y_bit,
896 driver_mask);
897 for (auto &bit : cell->connections_.at(ID::A)) {
898 bit.wire = module->wires_.at(remap_name(bit.wire->name));
899 bit2sinks[bit].push_back(cell);
900 }
901 }
902
903 //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires);
904 log("ABC RESULTS: input signals: %8d\n", in_wires);
905 log("ABC RESULTS: output signals: %8d\n", out_wires);
906
907 design->remove(mapped_mod);
908 }
909
910 struct Abc9OpsPass : public Pass {
911 Abc9OpsPass() : Pass("abc9_ops", "helper functions for ABC9") { }
912 void help() YS_OVERRIDE
913 {
914 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
915 log("\n");
916 log(" abc9_ops [options] [selection]\n");
917 log("\n");
918 log("This pass contains a set of supporting operations for use during ABC technology\n");
919 log("mapping, and is expected to be called in conjunction with other operations from\n");
920 log("the `abc9' script pass. Only fully-selected modules are supported.\n");
921 log("\n");
922 log(" -check\n");
923 log(" check that the design is valid, e.g. (* abc9_box_id *) values are unique,\n");
924 log(" (* abc9_carry *) is only given for one input/output port, etc.\n");
925 log("\n");
926 log(" -prep_delays\n");
927 log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n");
928 log(" certain delays, e.g. (* abc9_required *) values.\n");
929 log("\n");
930 log(" -mark_scc\n");
931 log(" for an arbitrarily chosen cell in each unique SCC of each selected module\n");
932 log(" (tagged with an (* abc9_scc_id = <int> *) attribute), temporarily mark all\n");
933 log(" wires driven by this cell's outputs with a (* keep *) attribute in order\n");
934 log(" to break the SCC. this temporary attribute will be removed on -reintegrate.\n");
935 log("\n");
936 log(" -prep_xaiger\n");
937 log(" prepare the design for XAIGER output. this includes computing the\n");
938 log(" topological ordering of ABC9 boxes, as well as preparing the\n");
939 log(" '<module-name>$holes' module that contains the logic behaviour of ABC9\n");
940 log(" whiteboxes.\n");
941 log("\n");
942 log(" -dff\n");
943 log(" consider flop cells (those instantiating modules marked with (* abc9_flop *)\n");
944 log(" during -prep_xaiger.\n");
945 log("\n");
946 log(" -prep_dff\n");
947 log(" compute the clock domain and initial value of each flop in the design.\n");
948 log(" process the '$holes' module to support clock-enable functionality.\n");
949 log("\n");
950 log(" -write_box (<src>|(null)) <dst>\n");
951 log(" copy the existing box file from <src> (skip if '(null)') and append any\n");
952 log(" new box definitions.\n");
953 log("\n");
954 log(" -reintegrate\n");
955 log(" for each selected module, re-intergrate the module '<module-name>$abc9'\n");
956 log(" by first recovering ABC9 boxes, and then stitching in the remaining primary\n");
957 log(" inputs and outputs.\n");
958 log("\n");
959 }
960 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
961 {
962 log_header(design, "Executing ABC9_OPS pass (helper functions for ABC9).\n");
963
964 bool check_mode = false;
965 bool prep_delays_mode = false;
966 bool mark_scc_mode = false;
967 bool prep_dff_mode = false;
968 bool prep_xaiger_mode = false;
969 bool reintegrate_mode = false;
970 bool dff_mode = false;
971 std::string write_box_src, write_box_dst;
972
973 size_t argidx;
974 for (argidx = 1; argidx < args.size(); argidx++) {
975 std::string arg = args[argidx];
976 if (arg == "-check") {
977 check_mode = true;
978 continue;
979 }
980 if (arg == "-mark_scc") {
981 mark_scc_mode = true;
982 continue;
983 }
984 if (arg == "-prep_dff") {
985 prep_dff_mode = true;
986 continue;
987 }
988 if (arg == "-prep_xaiger") {
989 prep_xaiger_mode = true;
990 continue;
991 }
992 if (arg == "-prep_delays") {
993 prep_delays_mode = true;
994 continue;
995 }
996 if (arg == "-write_box" && argidx+2 < args.size()) {
997 write_box_src = args[++argidx];
998 write_box_dst = args[++argidx];
999 rewrite_filename(write_box_src);
1000 rewrite_filename(write_box_dst);
1001 continue;
1002 }
1003 if (arg == "-reintegrate") {
1004 reintegrate_mode = true;
1005 continue;
1006 }
1007 if (arg == "-dff") {
1008 dff_mode = true;
1009 continue;
1010 }
1011 break;
1012 }
1013 extra_args(args, argidx, design);
1014
1015 if (!(check_mode || mark_scc_mode || prep_delays_mode || prep_xaiger_mode || prep_dff_mode || !write_box_src.empty() || reintegrate_mode))
1016 log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff}, -write_box, -reintegrate must be specified.\n");
1017
1018 if (dff_mode && !prep_xaiger_mode)
1019 log_cmd_error("'-dff' option is only relevant for -prep_xaiger.\n");
1020
1021 if (check_mode)
1022 check(design);
1023 if (prep_delays_mode)
1024 prep_delays(design);
1025
1026 for (auto mod : design->selected_modules()) {
1027 if (mod->get_bool_attribute("\\abc9_holes"))
1028 continue;
1029
1030 if (mod->processes.size() > 0) {
1031 log("Skipping module %s as it contains processes.\n", log_id(mod));
1032 continue;
1033 }
1034
1035 if (!design->selected_whole_module(mod))
1036 log_error("Can't handle partially selected module %s!\n", log_id(mod));
1037
1038 if (!write_box_src.empty())
1039 write_box(mod, write_box_src, write_box_dst);
1040 if (mark_scc_mode)
1041 mark_scc(mod);
1042 if (prep_dff_mode)
1043 prep_dff(mod);
1044 if (prep_xaiger_mode)
1045 prep_xaiger(mod, dff_mode);
1046 if (reintegrate_mode)
1047 reintegrate(mod);
1048 }
1049 }
1050 } Abc9OpsPass;
1051
1052 PRIVATE_NAMESPACE_END