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