abc9_ops: -prep_xaiger exclude (* abc9_keep *) wires from toposort
[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 #include "kernel/timinginfo.h"
26
27 USING_YOSYS_NAMESPACE
28 PRIVATE_NAMESPACE_BEGIN
29
30 int map_autoidx;
31
32 inline std::string remap_name(RTLIL::IdString abc9_name)
33 {
34 return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1);
35 }
36
37 void check(RTLIL::Design *design, bool dff_mode)
38 {
39 dict<IdString,IdString> box_lookup;
40 for (auto m : design->modules()) {
41 auto flop = m->get_bool_attribute(ID::abc9_flop);
42 auto it = m->attributes.find(ID::abc9_box_id);
43 if (!flop) {
44 if (it == m->attributes.end())
45 continue;
46 auto id = it->second.as_int();
47 auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name));
48 if (!r.second)
49 log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n",
50 log_id(m), id, log_id(r.first->second));
51 }
52
53 // Make carry in the last PI, and carry out the last PO
54 // since ABC requires it this way
55 IdString carry_in, carry_out;
56 for (const auto &port_name : m->ports) {
57 auto w = m->wire(port_name);
58 log_assert(w);
59 if (w->get_bool_attribute(ID::abc9_carry)) {
60 if (w->port_input) {
61 if (carry_in != IdString())
62 log_error("Module '%s' contains more than one (* abc9_carry *) input port.\n", log_id(m));
63 carry_in = port_name;
64 }
65 if (w->port_output) {
66 if (carry_out != IdString())
67 log_error("Module '%s' contains more than one (* abc9_carry *) output port.\n", log_id(m));
68 carry_out = port_name;
69 }
70 }
71 }
72
73 if (carry_in != IdString() && carry_out == IdString())
74 log_error("Module '%s' contains an (* abc9_carry *) input port but no output port.\n", log_id(m));
75 if (carry_in == IdString() && carry_out != IdString())
76 log_error("Module '%s' contains an (* abc9_carry *) output port but no input port.\n", log_id(m));
77
78 if (flop) {
79 int num_outputs = 0;
80 for (auto port_name : m->ports) {
81 auto wire = m->wire(port_name);
82 if (wire->port_output) num_outputs++;
83 }
84 if (num_outputs != 1)
85 log_error("Module '%s' with (* abc9_flop *) has %d outputs (expect 1).\n", log_id(m), num_outputs);
86 }
87 }
88
89 if (dff_mode) {
90 static pool<IdString> unsupported{
91 ID($adff), ID($dlatch), ID($dlatchsr), ID($sr),
92 ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
93 ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
94 ID($_DLATCH_N_), ID($_DLATCH_P_),
95 ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_),
96 ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_),
97 ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_)
98 };
99 pool<IdString> processed;
100 for (auto module : design->selected_modules())
101 for (auto cell : module->cells()) {
102 auto inst_module = design->module(cell->type);
103 if (!inst_module)
104 continue;
105 if (!inst_module->get_blackbox_attribute())
106 continue;
107 IdString derived_type;
108 Module *derived_module;
109 if (cell->parameters.empty()) {
110 derived_type = cell->type;
111 derived_module = inst_module;
112 }
113 else {
114 derived_type = inst_module->derive(design, cell->parameters);
115 derived_module = design->module(derived_type);
116 log_assert(derived_module);
117 }
118 if (!derived_module->get_bool_attribute(ID::abc9_flop))
119 continue;
120 if (derived_module->get_blackbox_attribute(true /* ignore_wb */))
121 log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", log_id(derived_type));
122
123 if (derived_module->has_processes())
124 Pass::call_on_module(design, derived_module, "proc");
125
126 bool found = false;
127 for (auto derived_cell : derived_module->cells()) {
128 if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) {
129 if (found)
130 log_error("Module '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(derived_module));
131 found = true;
132
133 SigBit Q = derived_cell->getPort(ID::Q);
134 log_assert(GetSize(Q.wire) == 1);
135
136 if (!Q.wire->port_output)
137 log_error("Module '%s' contains a %s cell where its 'Q' port does not drive a module output!\n", log_id(derived_module), log_id(derived_cell->type));
138
139 Const init = Q.wire->attributes.at(ID::init, State::Sx);
140 log_assert(GetSize(init) == 1);
141 }
142 else if (unsupported.count(derived_cell->type))
143 log_error("Module '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", log_id(derived_module), log_id(derived_cell->type));
144 }
145 }
146 }
147 }
148
149 void prep_hier(RTLIL::Design *design, bool dff_mode)
150 {
151 auto r = saved_designs.emplace("$abc9_unmap", nullptr);
152 if (r.second)
153 r.first->second = new Design;
154 Design *unmap_design = r.first->second;
155
156 static const pool<IdString> seq_types{
157 ID($dff), ID($dffsr), ID($adff),
158 ID($dlatch), ID($dlatchsr), ID($sr),
159 ID($mem),
160 ID($_DFF_N_), ID($_DFF_P_),
161 ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
162 ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),
163 ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
164 ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
165 ID($_DLATCH_N_), ID($_DLATCH_P_),
166 ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_),
167 ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_),
168 ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_)
169 };
170
171 for (auto module : design->selected_modules())
172 for (auto cell : module->cells()) {
173 auto inst_module = design->module(cell->type);
174 if (!inst_module)
175 continue;
176 if (!inst_module->get_blackbox_attribute())
177 continue;
178 IdString derived_type;
179 Module *derived_module;
180 if (cell->parameters.empty()) {
181 derived_type = cell->type;
182 derived_module = inst_module;
183 }
184 else {
185 derived_type = inst_module->derive(design, cell->parameters);
186 derived_module = design->module(derived_type);
187 }
188 if (derived_module->get_blackbox_attribute(true /* ignore_wb */))
189 continue;
190
191 if (derived_module->get_bool_attribute(ID::abc9_flop)) {
192 if (!dff_mode)
193 continue;
194 }
195 else {
196 if (!derived_module->get_bool_attribute(ID::abc9_box) && !derived_module->get_bool_attribute(ID::abc9_bypass))
197 continue;
198 }
199
200 if (!unmap_design->module(derived_type)) {
201 if (derived_module->has_processes())
202 Pass::call_on_module(design, derived_module, "proc");
203
204 if (derived_module->get_bool_attribute(ID::abc9_flop)) {
205 for (auto derived_cell : derived_module->cells())
206 if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) {
207 SigBit Q = derived_cell->getPort(ID::Q);
208 Const init = Q.wire->attributes.at(ID::init, State::Sx);
209 log_assert(GetSize(init) == 1);
210
211 // Block sequential synthesis on cells with (* init *) != 1'b0
212 // because ABC9 doesn't support them
213 if (init != State::S0) {
214 log_warning("Module '%s' contains a %s cell with non-zero initial state -- this is not unsupported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(derived_module), log_id(derived_cell->type));
215 derived_module->set_bool_attribute(ID::abc9_flop, false);
216 }
217 break;
218 }
219 }
220 else if (derived_module->get_bool_attribute(ID::abc9_box)) {
221 for (auto derived_cell : derived_module->cells())
222 if (seq_types.count(derived_cell->type)) {
223 derived_module->set_bool_attribute(ID::abc9_box, false);
224 derived_module->set_bool_attribute(ID::abc9_bypass);
225 break;
226 }
227 }
228
229 if (derived_type != cell->type) {
230 auto unmap_module = unmap_design->addModule(derived_type);
231 for (auto port : derived_module->ports) {
232 auto w = unmap_module->addWire(port, derived_module->wire(port));
233 // Do not propagate (* init *) values into the box,
234 // in fact, remove it from outside too
235 if (w->port_output && w->attributes.erase(ID::init)) {
236 auto r = unmap_module->addWire(stringf("\\_TECHMAP_REMOVEINIT_%s_", log_id(port)));
237 unmap_module->connect(r, State::S1);
238 }
239 }
240 unmap_module->ports = derived_module->ports;
241 unmap_module->check();
242
243 auto replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, cell->type);
244 for (const auto &conn : cell->connections()) {
245 auto w = unmap_module->wire(conn.first);
246 log_assert(w);
247 replace_cell->setPort(conn.first, w);
248 }
249 replace_cell->parameters = cell->parameters;
250 }
251 }
252
253 cell->type = derived_type;
254 cell->parameters.clear();
255 }
256 }
257
258 void prep_bypass(RTLIL::Design *design)
259 {
260 auto r = saved_designs.emplace("$abc9_map", nullptr);
261 if (r.second)
262 r.first->second = new Design;
263 Design *map_design = r.first->second;
264
265 r = saved_designs.emplace("$abc9_unmap", nullptr);
266 if (r.second)
267 r.first->second = new Design;
268 Design *unmap_design = r.first->second;
269
270 pool<IdString> processed;
271 for (auto module : design->selected_modules())
272 for (auto cell : module->cells()) {
273 if (!processed.insert(cell->type).second)
274 continue;
275 auto inst_module = design->module(cell->type);
276 if (!inst_module)
277 continue;
278 if (!inst_module->get_bool_attribute(ID::abc9_bypass))
279 continue;
280 log_assert(!inst_module->get_blackbox_attribute(true /* ignore_wb */));
281 log_assert(cell->parameters.empty());
282
283
284 // The idea is to create two techmap designs, one which maps:
285 //
286 // box u0 (.i(i), .o(o));
287 //
288 // to
289 //
290 // wire $abc9$o;
291 // box u0 (.i(i), .o($abc9_byp$o));
292 // box_$abc9_byp (.i(i), .$abc9_byp$o($abc9_byp$o), .o(o));
293 //
294 // the purpose being to move the (* abc9_box *) status from 'box'
295 // (which is stateful) to 'box_$abc9_byp' (which becomes a new
296 // combinatorial black- (not white-) box with all state elements
297 // removed). This has the effect of preserving any combinatorial
298 // paths through an otherwise sequential primitive -- e.g. LUTRAMs.
299 //
300 // The unmap design performs the reverse:
301 //
302 // wire $abc9$o;
303 // box u0 (.i(i), .o($abc9_byp$o));
304 // box_$abc9_byp (.i(i), .$abc9_byp$o($abc9_byp$o), .o(o));
305 //
306 // to:
307 //
308 // wire $abc9$o;
309 // box u0 (.i(i), .o($abc9_byp$o));
310 // assign o = $abc9_byp$o;
311
312
313 // Copy inst_module into map_design, with the same interface
314 // and duplicate $abc9$* wires for its output ports
315 auto map_module = map_design->addModule(cell->type);
316 for (auto port_name : inst_module->ports) {
317 auto w = map_module->addWire(port_name, inst_module->wire(port_name));
318 if (w->port_output)
319 w->attributes.erase(ID::init);
320 }
321 map_module->ports = inst_module->ports;
322 map_module->check();
323 map_module->set_bool_attribute(ID::whitebox);
324
325 // Create the bypass module in the user design, which has the same
326 // interface as the derived module but with additional input
327 // ports driven by the outputs of the replaced cell
328 auto bypass_module = design->addModule(cell->type.str() + "_$abc9_byp");
329 for (auto port_name : inst_module->ports) {
330 auto port = inst_module->wire(port_name);
331 if (!port->port_output)
332 continue;
333 auto dst = bypass_module->addWire(port_name, port);
334 auto src = bypass_module->addWire("$abc9byp$" + port_name.str(), GetSize(port));
335 src->port_input = true;
336 // For these new input ports driven by the replaced
337 // cell, then create a new simple-path specify entry:
338 // (input => output) = 0
339 auto specify = bypass_module->addCell(NEW_ID, ID($specify2));
340 specify->setPort(ID::EN, State::S1);
341 specify->setPort(ID::SRC, src);
342 specify->setPort(ID::DST, dst);
343 specify->setParam(ID::FULL, 0);
344 specify->setParam(ID::SRC_WIDTH, GetSize(src));
345 specify->setParam(ID::DST_WIDTH, GetSize(dst));
346 specify->setParam(ID::SRC_DST_PEN, 0);
347 specify->setParam(ID::SRC_DST_POL, 0);
348 specify->setParam(ID::T_RISE_MIN, 0);
349 specify->setParam(ID::T_RISE_TYP, 0);
350 specify->setParam(ID::T_RISE_MAX, 0);
351 specify->setParam(ID::T_FALL_MIN, 0);
352 specify->setParam(ID::T_FALL_TYP, 0);
353 specify->setParam(ID::T_FALL_MAX, 0);
354 }
355 bypass_module->set_bool_attribute(ID::blackbox);
356 bypass_module->set_bool_attribute(ID::abc9_box);
357
358 // Copy any 'simple' (combinatorial) specify paths from
359 // the derived module into the bypass module, if EN
360 // is not false and SRC/DST are driven only by
361 // module ports; create new input port if one doesn't
362 // already exist
363 for (auto cell : inst_module->cells()) {
364 if (cell->type != ID($specify2))
365 continue;
366 auto EN = cell->getPort(ID::EN).as_bit();
367 SigBit newEN;
368 if (!EN.wire && EN != State::S1)
369 continue;
370 auto SRC = cell->getPort(ID::SRC);
371 for (const auto &c : SRC.chunks())
372 if (c.wire && !c.wire->port_input) {
373 SRC = SigSpec();
374 break;
375 }
376 if (SRC.empty())
377 continue;
378 auto DST = cell->getPort(ID::DST);
379 for (const auto &c : DST.chunks())
380 if (c.wire && !c.wire->port_output) {
381 DST = SigSpec();
382 break;
383 }
384 if (DST.empty())
385 continue;
386 auto rw = [bypass_module](RTLIL::SigSpec &sig)
387 {
388 SigSpec new_sig;
389 for (auto c : sig.chunks()) {
390 if (c.wire) {
391 auto port = bypass_module->wire(c.wire->name);
392 if (!port)
393 port = bypass_module->addWire(c.wire->name, c.wire);
394 c.wire = port;
395 }
396 new_sig.append(std::move(c));
397 }
398 sig = std::move(new_sig);
399 };
400 auto specify = bypass_module->addCell(NEW_ID, cell);
401 specify->rewrite_sigspecs(rw);
402 }
403 bypass_module->fixup_ports();
404
405 // Create an _TECHMAP_REPLACE_ cell identical to the original cell,
406 // and a bypass cell that has the same inputs/outputs as the
407 // original cell, but with additional inputs taken from the
408 // replaced cell
409 auto replace_cell = map_module->addCell(ID::_TECHMAP_REPLACE_, cell->type);
410 auto bypass_cell = map_module->addCell(NEW_ID, cell->type.str() + "_$abc9_byp");
411 for (const auto &conn : cell->connections()) {
412 auto port = map_module->wire(conn.first);
413 if (cell->input(conn.first)) {
414 replace_cell->setPort(conn.first, port);
415 if (bypass_module->wire(conn.first))
416 bypass_cell->setPort(conn.first, port);
417 }
418 if (cell->output(conn.first)) {
419 bypass_cell->setPort(conn.first, port);
420 auto n = "$abc9byp$" + conn.first.str();
421 auto w = map_module->addWire(n, GetSize(conn.second));
422 replace_cell->setPort(conn.first, w);
423 bypass_cell->setPort(n, w);
424 }
425 }
426
427
428 // Lastly, create a new module in the unmap_design that shorts
429 // out the bypass cell back to leave the replace cell behind
430 // driving the outputs
431 auto unmap_module = unmap_design->addModule(cell->type.str() + "_$abc9_byp");
432 for (auto port_name : inst_module->ports) {
433 auto w = unmap_module->addWire(port_name, inst_module->wire(port_name));
434 if (w->port_output) {
435 w->attributes.erase(ID::init);
436 auto w2 = unmap_module->addWire("$abc9byp$" + port_name.str(), GetSize(w));
437 w2->port_input = true;
438 unmap_module->connect(w, w2);
439 }
440 }
441 unmap_module->fixup_ports();
442 }
443 }
444
445 void prep_dff(RTLIL::Design *design)
446 {
447 auto r = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection(false)));
448 auto &modules_sel = r.first->second;
449
450 for (auto module : design->selected_modules())
451 for (auto cell : module->cells()) {
452 if (modules_sel.selected_whole_module(cell->type))
453 continue;
454 auto inst_module = design->module(cell->type);
455 if (!inst_module)
456 continue;
457 if (!inst_module->get_bool_attribute(ID::abc9_flop))
458 continue;
459 log_assert(!inst_module->get_blackbox_attribute(true /* ignore_wb */));
460 log_assert(cell->parameters.empty());
461 modules_sel.select(inst_module);
462 }
463 }
464
465 void prep_dff_submod(RTLIL::Design *design)
466 {
467 for (auto module : design->modules()) {
468 vector<Cell*> specify_cells;
469 SigBit Q;
470 Cell* dff_cell = nullptr;
471
472 if (!module->get_bool_attribute(ID::abc9_flop))
473 continue;
474
475 for (auto cell : module->cells())
476 if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) {
477 log_assert(!dff_cell);
478 dff_cell = cell;
479 Q = cell->getPort(ID::Q);
480 log_assert(GetSize(Q.wire) == 1);
481 }
482 else if (cell->type.in(ID($specify3), ID($specrule)))
483 specify_cells.emplace_back(cell);
484 log_assert(dff_cell);
485
486 // Add an always-enabled CE mux that drives $_DFF_[NP]_.D so that:
487 // (a) flop box will have an output
488 // (b) $_DFF_[NP]_.Q will be present as an input
489 SigBit D = module->addWire(NEW_ID);
490 module->addMuxGate(NEW_ID, dff_cell->getPort(ID::D), Q, State::S0, D);
491 dff_cell->setPort(ID::D, D);
492
493 // Rewrite $specify cells that end with $_DFF_[NP]_.Q
494 // to $_DFF_[NP]_.D since it will be moved into
495 // the submodule
496 for (auto cell : specify_cells) {
497 auto DST = cell->getPort(ID::DST);
498 DST.replace(Q, D);
499 cell->setPort(ID::DST, DST);
500 }
501
502 design->scratchpad_set_bool("abc9_ops.prep_dff_submod.did_something", true);
503 }
504 }
505
506 void prep_dff_unmap(RTLIL::Design *design)
507 {
508 Design *unmap_design = saved_designs.at("$abc9_unmap");
509
510 for (auto module : design->modules()) {
511 if (!module->get_bool_attribute(ID::abc9_flop) || module->get_bool_attribute(ID::abc9_box))
512 continue;
513
514 // Make sure the box module has all the same ports present on flop cell
515 auto replace_cell = module->cell(ID::_TECHMAP_REPLACE_);
516 log_assert(replace_cell);
517 auto box_module = design->module(module->name.str() + "_$abc9_flop");
518 log_assert(box_module);
519 for (auto port_name : module->ports) {
520 auto port = module->wire(port_name);
521 auto box_port = box_module->wire(port_name);
522 if (box_port) {
523 // Do not propagate init -- already captured by box
524 box_port->attributes.erase(ID::init);
525 continue;
526 }
527 log_assert(port->port_input);
528 box_module->addWire(port_name, port);
529 replace_cell->setPort(port_name, port);
530 }
531 box_module->fixup_ports();
532
533 auto unmap_module = unmap_design->addModule(box_module->name);
534 replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, module->name);
535 for (auto port_name : box_module->ports) {
536 auto w = unmap_module->addWire(port_name, box_module->wire(port_name));
537 if (module->wire(port_name))
538 replace_cell->setPort(port_name, w);
539 }
540 unmap_module->ports = box_module->ports;
541 unmap_module->check();
542 }
543 }
544
545 void mark_scc(RTLIL::Module *module)
546 {
547 // For every unique SCC found, (arbitrarily) find the first
548 // cell in the component, and replace its output connections
549 // with a new wire driven by the old connection but with a
550 // special (* abc9_keep *) attribute set (which is used by
551 // write_xaiger to break this wire into PI and POs)
552 pool<RTLIL::Const> ids_seen;
553 for (auto cell : module->cells()) {
554 auto it = cell->attributes.find(ID::abc9_scc_id);
555 if (it == cell->attributes.end())
556 continue;
557 auto id = it->second;
558 auto r = ids_seen.insert(id);
559 cell->attributes.erase(it);
560 if (!r.second)
561 continue;
562 for (auto &c : cell->connections_) {
563 if (c.second.is_fully_const()) continue;
564 if (cell->output(c.first)) {
565 Wire *w = module->addWire(NEW_ID, GetSize(c.second));
566 w->set_bool_attribute(ID::abc9_keep);
567 module->connect(w, c.second);
568 c.second = w;
569 }
570 }
571 }
572 }
573
574 void prep_delays(RTLIL::Design *design, bool dff_mode)
575 {
576 TimingInfo timing;
577
578 // Derive all Yosys blackbox modules that are not combinatorial abc9 boxes
579 // (e.g. DSPs, RAMs, etc.) nor abc9 flops and collect all such instantiations
580 std::vector<Cell*> cells;
581 for (auto module : design->selected_modules()) {
582 if (module->processes.size() > 0) {
583 log("Skipping module %s as it contains processes.\n", log_id(module));
584 continue;
585 }
586
587 for (auto cell : module->cells()) {
588 if (cell->type.in(ID($_AND_), ID($_NOT_), ID($_DFF_N_), ID($_DFF_P_)))
589 continue;
590 log_assert(!cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY="));
591
592 RTLIL::Module* inst_module = design->module(cell->type);
593 if (!inst_module)
594 continue;
595 if (!inst_module->get_blackbox_attribute())
596 continue;
597 if (!cell->parameters.empty())
598 continue;
599
600 if (inst_module->get_bool_attribute(ID::abc9_box))
601 continue;
602 if (inst_module->get_bool_attribute(ID::abc9_bypass))
603 continue;
604
605 if (dff_mode && inst_module->get_bool_attribute(ID::abc9_flop)) {
606 continue; // do not add $__ABC9_DELAY boxes to flops
607 // as delays will be captured in the flop box
608 }
609
610 if (!timing.count(cell->type))
611 timing.setup_module(inst_module);
612
613 cells.emplace_back(cell);
614 }
615 }
616
617 // Insert $__ABC9_DELAY cells on all cells that instantiate blackboxes
618 // (or bypassed white-boxes with required times)
619 dict<int, IdString> box_cache;
620 Module *delay_module = design->module(ID($__ABC9_DELAY));
621 log_assert(delay_module);
622 for (auto cell : cells) {
623 auto module = cell->module;
624 auto inst_module = design->module(cell->type);
625 log_assert(inst_module);
626
627 auto &t = timing.at(cell->type).required;
628 for (auto &conn : cell->connections_) {
629 auto port_wire = inst_module->wire(conn.first);
630 if (!port_wire)
631 log_error("Port %s in cell %s (type %s) from module %s does not actually exist",
632 log_id(conn.first), log_id(cell), log_id(cell->type), log_id(module));
633 if (!port_wire->port_input)
634 continue;
635 if (conn.second.is_fully_const())
636 continue;
637
638 SigSpec O = module->addWire(NEW_ID, GetSize(conn.second));
639 for (int i = 0; i < GetSize(conn.second); i++) {
640 auto d = t.at(TimingInfo::NameBit(conn.first,i), 0);
641 if (d == 0)
642 continue;
643
644 #ifndef NDEBUG
645 if (ys_debug(1)) {
646 static std::set<std::tuple<IdString,IdString,int>> seen;
647 if (seen.emplace(cell->type, conn.first, i).second) log("%s.%s[%d] abc9_required = %d\n",
648 log_id(cell->type), log_id(conn.first), i, d);
649 }
650 #endif
651 auto r = box_cache.insert(d);
652 if (r.second) {
653 r.first->second = delay_module->derive(design, {{ID::DELAY, d}});
654 log_assert(r.first->second.begins_with("$paramod$__ABC9_DELAY\\DELAY="));
655 }
656 auto box = module->addCell(NEW_ID, r.first->second);
657 box->setPort(ID::I, conn.second[i]);
658 box->setPort(ID::O, O[i]);
659 conn.second[i] = O[i];
660 }
661 }
662 }
663 }
664
665 void prep_xaiger(RTLIL::Module *module, bool dff)
666 {
667 auto design = module->design;
668 log_assert(design);
669
670 SigMap sigmap(module);
671
672 dict<SigBit, pool<IdString>> bit_drivers, bit_users;
673 TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
674 dict<IdString, std::vector<IdString>> box_ports;
675
676 for (auto cell : module->cells()) {
677 if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
678 continue;
679 if (cell->has_keep_attr())
680 continue;
681
682 auto inst_module = design->module(cell->type);
683 bool abc9_flop = inst_module && inst_module->get_bool_attribute(ID::abc9_flop);
684 if (abc9_flop && !dff)
685 continue;
686
687 if (inst_module && inst_module->get_bool_attribute(ID::abc9_box)) {
688 auto r = box_ports.insert(cell->type);
689 if (r.second) {
690 // Make carry in the last PI, and carry out the last PO
691 // since ABC requires it this way
692 IdString carry_in, carry_out;
693 for (const auto &port_name : inst_module->ports) {
694 auto w = inst_module->wire(port_name);
695 log_assert(w);
696 if (w->get_bool_attribute(ID::abc9_carry)) {
697 log_assert(w->port_input != w->port_output);
698 if (w->port_input)
699 carry_in = port_name;
700 else if (w->port_output)
701 carry_out = port_name;
702 }
703 else
704 r.first->second.push_back(port_name);
705 }
706 if (carry_in != IdString()) {
707 r.first->second.push_back(carry_in);
708 r.first->second.push_back(carry_out);
709 }
710 }
711 }
712 else if (!yosys_celltypes.cell_known(cell->type))
713 continue;
714
715 // TODO: Speed up toposort -- we care about box ordering only
716 for (auto conn : cell->connections()) {
717 if (cell->input(conn.first))
718 for (auto bit : sigmap(conn.second))
719 bit_users[bit].insert(cell->name);
720
721 if (cell->output(conn.first) && !abc9_flop)
722 for (const auto &chunk : conn.second.chunks())
723 if (!chunk.wire->get_bool_attribute(ID::abc9_keep))
724 for (auto b : sigmap(SigSpec(chunk)))
725 bit_drivers[b].insert(cell->name);
726 }
727 toposort.node(cell->name);
728 }
729
730 if (box_ports.empty())
731 return;
732
733 for (auto &it : bit_users)
734 if (bit_drivers.count(it.first))
735 for (auto driver_cell : bit_drivers.at(it.first))
736 for (auto user_cell : it.second)
737 toposort.edge(driver_cell, user_cell);
738
739 if (ys_debug(1))
740 toposort.analyze_loops = true;
741
742 bool no_loops YS_ATTRIBUTE(unused) = toposort.sort();
743
744 if (ys_debug(1)) {
745 unsigned i = 0;
746 for (auto &it : toposort.loops) {
747 log(" loop %d\n", i++);
748 for (auto cell_name : it) {
749 auto cell = module->cell(cell_name);
750 log_assert(cell);
751 log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute().c_str());
752 }
753 }
754 }
755
756 log_assert(no_loops);
757
758 auto r = saved_designs.emplace("$abc9_holes", nullptr);
759 if (r.second)
760 r.first->second = new Design;
761 RTLIL::Design *holes_design = r.first->second;
762 log_assert(holes_design);
763 RTLIL::Module *holes_module = holes_design->addModule(module->name);
764 log_assert(holes_module);
765
766 dict<IdString, Cell*> cell_cache;
767 TimingInfo timing;
768
769 int port_id = 1, box_count = 0;
770 for (auto cell_name : toposort.sorted) {
771 RTLIL::Cell *cell = module->cell(cell_name);
772 log_assert(cell);
773
774 RTLIL::Module* box_module = design->module(cell->type);
775 if (!box_module)
776 continue;
777 if (!box_module->get_bool_attribute(ID::abc9_box))
778 continue;
779 log_assert(cell->parameters.empty());
780 log_assert(box_module->get_blackbox_attribute());
781
782 cell->attributes[ID::abc9_box_seq] = box_count++;
783
784 auto r = cell_cache.insert(cell->type);
785 auto &holes_cell = r.first->second;
786 if (r.second) {
787 if (box_module->get_bool_attribute(ID::whitebox)) {
788 holes_cell = holes_module->addCell(cell->name, cell->type);
789
790 if (box_module->has_processes())
791 Pass::call_on_module(design, box_module, "proc");
792
793 int box_inputs = 0;
794 for (auto port_name : box_ports.at(cell->type)) {
795 RTLIL::Wire *w = box_module->wire(port_name);
796 log_assert(w);
797 log_assert(!w->port_input || !w->port_output);
798 auto &conn = holes_cell->connections_[port_name];
799 if (w->port_input) {
800 for (int i = 0; i < GetSize(w); i++) {
801 box_inputs++;
802 RTLIL::Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs));
803 if (!holes_wire) {
804 holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs));
805 holes_wire->port_input = true;
806 holes_wire->port_id = port_id++;
807 holes_module->ports.push_back(holes_wire->name);
808 }
809 conn.append(holes_wire);
810 }
811 }
812 else if (w->port_output)
813 conn = holes_module->addWire(stringf("%s.%s", cell->type.c_str(), log_id(port_name)), GetSize(w));
814 }
815 }
816 else // box_module is a blackbox
817 log_assert(holes_cell == nullptr);
818 }
819
820 for (auto port_name : box_ports.at(cell->type)) {
821 RTLIL::Wire *w = box_module->wire(port_name);
822 log_assert(w);
823 if (!w->port_output)
824 continue;
825 Wire *holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name.c_str(), log_id(port_name)), GetSize(w));
826 holes_wire->port_output = true;
827 holes_wire->port_id = port_id++;
828 holes_module->ports.push_back(holes_wire->name);
829 if (holes_cell) // whitebox
830 holes_module->connect(holes_wire, holes_cell->getPort(port_name));
831 else // blackbox
832 holes_module->connect(holes_wire, Const(State::S0, GetSize(w)));
833 }
834 }
835 }
836
837 void prep_lut(RTLIL::Design *design, int maxlut)
838 {
839 TimingInfo timing;
840
841 struct t_lut {
842 IdString name;
843 int area;
844 std::vector<int> delays;
845 };
846 std::map<int,t_lut> table;
847 for (auto module : design->modules()) {
848 auto it = module->attributes.find(ID::abc9_lut);
849 if (it == module->attributes.end())
850 continue;
851
852 auto &t = timing.setup_module(module);
853
854 TimingInfo::NameBit o;
855 std::vector<int> delays;
856 for (const auto &i : t.comb) {
857 auto &d = i.first.second;
858 if (o == TimingInfo::NameBit())
859 o = d;
860 else if (o != d)
861 log_error("Module '%s' with (* abc9_lut *) has more than one output.\n", log_id(module));
862 delays.push_back(i.second);
863 }
864
865 if (GetSize(delays) == 0)
866 log_error("Module '%s' with (* abc9_lut *) has no specify entries.\n", log_id(module));
867 if (maxlut && GetSize(delays) > maxlut)
868 continue;
869 // ABC requires non-decreasing LUT input delays
870 std::sort(delays.begin(), delays.end());
871
872 int K = GetSize(delays);
873 auto entry = t_lut{module->name, it->second.as_int(), std::move(delays)};
874 auto r = table.emplace(K, entry);
875 if (!r.second) {
876 if (r.first->second.area != entry.area)
877 log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", log_id(module), log_id(r.first->second.name));
878 if (r.first->second.delays != entry.delays)
879 log_error("Modules '%s' and '%s' have conflicting specify entries.\n", log_id(module), log_id(r.first->second.name));
880 }
881 }
882
883 if (table.empty())
884 log_error("Design does not contain any modules with (* abc9_lut *).\n");
885
886 std::stringstream ss;
887 const auto &front = *table.begin();
888 // If the first entry does not start from a 1-input LUT,
889 // (as ABC requires) crop the first entry to do so
890 for (int i = 1; i < front.first; i++) {
891 ss << "# $__ABC9_LUT" << i << std::endl;
892 ss << i << " " << front.second.area;
893 for (int j = 0; j < i; j++)
894 ss << " " << front.second.delays[j];
895 ss << std::endl;
896 }
897 for (const auto &i : table) {
898 ss << "# " << log_id(i.second.name) << std::endl;
899 ss << i.first << " " << i.second.area;
900 for (const auto &j : i.second.delays)
901 ss << " " << j;
902 ss << std::endl;
903 }
904 design->scratchpad_set_string("abc9_ops.lut_library", ss.str());
905 }
906
907 void write_lut(RTLIL::Module *module, const std::string &dst) {
908 std::ofstream ofs(dst);
909 log_assert(ofs.is_open());
910 ofs << module->design->scratchpad_get_string("abc9_ops.lut_library");
911 ofs.close();
912 }
913
914 void prep_box(RTLIL::Design *design)
915 {
916 TimingInfo timing;
917
918 std::stringstream ss;
919 int abc9_box_id = 1;
920 for (auto module : design->modules()) {
921 auto it = module->attributes.find(ID::abc9_box_id);
922 if (it == module->attributes.end())
923 continue;
924 abc9_box_id = std::max(abc9_box_id, it->second.as_int());
925 }
926
927 dict<IdString,std::vector<IdString>> box_ports;
928 for (auto module : design->modules()) {
929 auto it = module->attributes.find(ID::abc9_box);
930 if (it == module->attributes.end())
931 continue;
932 bool box = it->second.as_bool();
933 module->attributes.erase(it);
934 if (!box)
935 continue;
936
937 auto r = module->attributes.insert(ID::abc9_box_id);
938 if (!r.second)
939 continue;
940 r.first->second = abc9_box_id++;
941
942 if (module->get_bool_attribute(ID::abc9_flop)) {
943 int num_inputs = 0, num_outputs = 0;
944 for (auto port_name : module->ports) {
945 auto wire = module->wire(port_name);
946 log_assert(GetSize(wire) == 1);
947 if (wire->port_input) num_inputs++;
948 if (wire->port_output) num_outputs++;
949 }
950 log_assert(num_outputs == 1);
951
952 ss << log_id(module) << " " << r.first->second.as_int();
953 log_assert(module->get_bool_attribute(ID::whitebox));
954 ss << " " << "1";
955 ss << " " << num_inputs << " " << num_outputs << std::endl;
956
957 ss << "#";
958 bool first = true;
959 for (auto port_name : module->ports) {
960 auto wire = module->wire(port_name);
961 if (!wire->port_input)
962 continue;
963 if (first)
964 first = false;
965 else
966 ss << " ";
967 ss << log_id(wire);
968 }
969 ss << std::endl;
970
971 auto &t = timing.setup_module(module).required;
972 if (t.empty())
973 log_error("Module '%s' with (* abc9_flop *) has no clk-to-q timing (and thus no connectivity) information.\n", log_id(module));
974
975 first = true;
976 for (auto port_name : module->ports) {
977 auto wire = module->wire(port_name);
978 if (!wire->port_input)
979 continue;
980 if (first)
981 first = false;
982 else
983 ss << " ";
984 log_assert(GetSize(wire) == 1);
985 auto it = t.find(TimingInfo::NameBit(port_name,0));
986 if (it == t.end())
987 // Assume no connectivity if no setup time
988 ss << "-";
989 else {
990 ss << it->second;
991
992 #ifndef NDEBUG
993 if (ys_debug(1)) {
994 static std::set<std::pair<IdString,IdString>> seen;
995 if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module),
996 log_id(port_name), it->second);
997 }
998 #endif
999 }
1000 }
1001 ss << " # $_DFF_[NP]_.D" << std::endl;
1002 ss << std::endl;
1003 }
1004 else {
1005 auto r2 = box_ports.insert(module->name);
1006 if (r2.second) {
1007 // Make carry in the last PI, and carry out the last PO
1008 // since ABC requires it this way
1009 IdString carry_in, carry_out;
1010 for (const auto &port_name : module->ports) {
1011 auto w = module->wire(port_name);
1012 log_assert(w);
1013 if (w->get_bool_attribute(ID::abc9_carry)) {
1014 log_assert(w->port_input != w->port_output);
1015 if (w->port_input)
1016 carry_in = port_name;
1017 else if (w->port_output)
1018 carry_out = port_name;
1019 }
1020 else
1021 r2.first->second.push_back(port_name);
1022 }
1023
1024 if (carry_in != IdString()) {
1025 r2.first->second.push_back(carry_in);
1026 r2.first->second.push_back(carry_out);
1027 }
1028 }
1029
1030 std::vector<SigBit> inputs, outputs;
1031 for (auto port_name : r2.first->second) {
1032 auto wire = module->wire(port_name);
1033 if (wire->port_input)
1034 for (int i = 0; i < GetSize(wire); i++)
1035 inputs.emplace_back(wire, i);
1036 if (wire->port_output)
1037 for (int i = 0; i < GetSize(wire); i++)
1038 outputs.emplace_back(wire, i);
1039 }
1040
1041 ss << log_id(module) << " " << module->attributes.at(ID::abc9_box_id).as_int();
1042 ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0");
1043 ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl;
1044
1045 bool first = true;
1046 ss << "#";
1047 for (const auto &i : inputs) {
1048 if (first)
1049 first = false;
1050 else
1051 ss << " ";
1052 if (GetSize(i.wire) == 1)
1053 ss << log_id(i.wire);
1054 else
1055 ss << log_id(i.wire) << "[" << i.offset << "]";
1056 }
1057 ss << std::endl;
1058
1059 auto &t = timing.setup_module(module);
1060 if (t.comb.empty())
1061 log_error("Module '%s' with (* abc9_box *) has no timing (and thus no connectivity) information.\n", log_id(module));
1062
1063 for (const auto &o : outputs) {
1064 first = true;
1065 for (const auto &i : inputs) {
1066 if (first)
1067 first = false;
1068 else
1069 ss << " ";
1070 auto jt = t.comb.find(TimingInfo::BitBit(i,o));
1071 if (jt == t.comb.end())
1072 ss << "-";
1073 else
1074 ss << jt->second;
1075 }
1076 ss << " # ";
1077 if (GetSize(o.wire) == 1)
1078 ss << log_id(o.wire);
1079 else
1080 ss << log_id(o.wire) << "[" << o.offset << "]";
1081 ss << std::endl;
1082 }
1083 ss << std::endl;
1084 }
1085 }
1086
1087 // ABC expects at least one box
1088 if (ss.tellp() == 0)
1089 ss << "(dummy) 1 0 0 0";
1090
1091 design->scratchpad_set_string("abc9_ops.box_library", ss.str());
1092 }
1093
1094 void write_box(RTLIL::Module *module, const std::string &dst) {
1095 std::ofstream ofs(dst);
1096 log_assert(ofs.is_open());
1097 ofs << module->design->scratchpad_get_string("abc9_ops.box_library");
1098 ofs.close();
1099 }
1100
1101 void reintegrate(RTLIL::Module *module, bool dff_mode)
1102 {
1103 auto design = module->design;
1104 log_assert(design);
1105
1106 map_autoidx = autoidx++;
1107
1108 RTLIL::Module *mapped_mod = design->module(stringf("%s$abc9", module->name.c_str()));
1109 if (mapped_mod == NULL)
1110 log_error("ABC output file does not contain a module `%s$abc'.\n", log_id(module));
1111
1112 for (auto w : mapped_mod->wires()) {
1113 auto nw = module->addWire(remap_name(w->name), GetSize(w));
1114 nw->start_offset = w->start_offset;
1115 // Remove all (* init *) since they only existon $_DFF_[NP]_
1116 w->attributes.erase(ID::init);
1117 }
1118
1119 dict<IdString,std::vector<IdString>> box_ports;
1120
1121 for (auto m : design->modules()) {
1122 if (!m->attributes.count(ID::abc9_box_id))
1123 continue;
1124
1125 auto r = box_ports.insert(m->name);
1126 if (!r.second)
1127 continue;
1128
1129 // Make carry in the last PI, and carry out the last PO
1130 // since ABC requires it this way
1131 IdString carry_in, carry_out;
1132 for (const auto &port_name : m->ports) {
1133 auto w = m->wire(port_name);
1134 log_assert(w);
1135 if (w->get_bool_attribute(ID::abc9_carry)) {
1136 log_assert(w->port_input != w->port_output);
1137 if (w->port_input)
1138 carry_in = port_name;
1139 else if (w->port_output)
1140 carry_out = port_name;
1141 }
1142 else
1143 r.first->second.push_back(port_name);
1144 }
1145
1146 if (carry_in != IdString()) {
1147 r.first->second.push_back(carry_in);
1148 r.first->second.push_back(carry_out);
1149 }
1150 }
1151
1152 std::vector<Cell*> boxes;
1153 for (auto cell : module->cells().to_vector()) {
1154 if (cell->has_keep_attr())
1155 continue;
1156
1157 // Short out $_DFF_[NP]_ cells since the flop box already has
1158 // all the information we need to reconstruct cell
1159 if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_)) && !cell->get_bool_attribute(ID::abc9_keep)) {
1160 module->connect(cell->getPort(ID::Q), cell->getPort(ID::D));
1161 module->remove(cell);
1162 }
1163 else if (cell->type.in(ID($_AND_), ID($_NOT_)))
1164 module->remove(cell);
1165 else if (cell->attributes.erase(ID::abc9_box_seq))
1166 boxes.emplace_back(cell);
1167 }
1168
1169 dict<SigBit, pool<IdString>> bit_drivers, bit_users;
1170 TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
1171 dict<RTLIL::Cell*,RTLIL::Cell*> not2drivers;
1172 dict<SigBit, std::vector<RTLIL::Cell*>> bit2sinks;
1173
1174 std::map<IdString, int> cell_stats;
1175 for (auto mapped_cell : mapped_mod->cells())
1176 {
1177 // Short out $_FF_ cells since the flop box already has
1178 // all the information we need to reconstruct cell
1179 if (dff_mode && mapped_cell->type == ID($_FF_)) {
1180 SigBit D = mapped_cell->getPort(ID::D);
1181 SigBit Q = mapped_cell->getPort(ID::Q);
1182 if (D.wire)
1183 D.wire = module->wires_.at(remap_name(D.wire->name));
1184 Q.wire = module->wires_.at(remap_name(Q.wire->name));
1185 module->connect(Q, D);
1186 continue;
1187 }
1188
1189 // TODO: Speed up toposort -- we care about NOT ordering only
1190 toposort.node(mapped_cell->name);
1191
1192 if (mapped_cell->type == ID($_NOT_)) {
1193 RTLIL::SigBit a_bit = mapped_cell->getPort(ID::A);
1194 RTLIL::SigBit y_bit = mapped_cell->getPort(ID::Y);
1195 bit_users[a_bit].insert(mapped_cell->name);
1196 // Ignore inouts for topo ordering
1197 if (y_bit.wire && !(y_bit.wire->port_input && y_bit.wire->port_output))
1198 bit_drivers[y_bit].insert(mapped_cell->name);
1199
1200 if (!a_bit.wire) {
1201 mapped_cell->setPort(ID::Y, module->addWire(NEW_ID));
1202 RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name));
1203 log_assert(wire);
1204 module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1);
1205 }
1206 else {
1207 RTLIL::Cell* driver_lut = nullptr;
1208 // ABC can return NOT gates that drive POs
1209 if (!a_bit.wire->port_input) {
1210 // If it's not a NOT gate that that comes from a PI directly,
1211 // find the driver LUT and clone that to guarantee that we won't
1212 // increase the max logic depth
1213 // (TODO: Optimise by not cloning unless will increase depth)
1214 RTLIL::IdString driver_name;
1215 if (GetSize(a_bit.wire) == 1)
1216 driver_name = stringf("$lut%s", a_bit.wire->name.c_str());
1217 else
1218 driver_name = stringf("$lut%s[%d]", a_bit.wire->name.c_str(), a_bit.offset);
1219 driver_lut = mapped_mod->cell(driver_name);
1220 }
1221
1222 if (!driver_lut) {
1223 // If a driver couldn't be found (could be from PI or box CI)
1224 // then implement using a LUT
1225 RTLIL::Cell *cell = module->addLut(remap_name(stringf("$lut%s", mapped_cell->name.c_str())),
1226 RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset),
1227 RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset),
1228 RTLIL::Const::from_string("01"));
1229 bit2sinks[cell->getPort(ID::A)].push_back(cell);
1230 cell_stats[ID($lut)]++;
1231 }
1232 else
1233 not2drivers[mapped_cell] = driver_lut;
1234 }
1235 continue;
1236 }
1237
1238 if (mapped_cell->type == ID($lut)) {
1239 RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
1240 cell->parameters = mapped_cell->parameters;
1241 cell->attributes = mapped_cell->attributes;
1242
1243 for (auto &mapped_conn : mapped_cell->connections()) {
1244 RTLIL::SigSpec newsig;
1245 for (auto c : mapped_conn.second.chunks()) {
1246 if (c.width == 0)
1247 continue;
1248 //log_assert(c.width == 1);
1249 if (c.wire)
1250 c.wire = module->wires_.at(remap_name(c.wire->name));
1251 newsig.append(c);
1252 }
1253 cell->setPort(mapped_conn.first, newsig);
1254
1255 if (cell->input(mapped_conn.first)) {
1256 for (auto i : newsig)
1257 bit2sinks[i].push_back(cell);
1258 for (auto i : mapped_conn.second)
1259 bit_users[i].insert(mapped_cell->name);
1260 }
1261 if (cell->output(mapped_conn.first))
1262 for (auto i : mapped_conn.second)
1263 // Ignore inouts for topo ordering
1264 if (i.wire && !(i.wire->port_input && i.wire->port_output))
1265 bit_drivers[i].insert(mapped_cell->name);
1266 }
1267 }
1268 else {
1269 RTLIL::Cell *existing_cell = module->cell(mapped_cell->name);
1270 if (!existing_cell)
1271 log_error("Cannot find existing box cell with name '%s' in original design.\n", log_id(mapped_cell));
1272
1273 if (existing_cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) {
1274 SigBit I = mapped_cell->getPort(ID(i));
1275 SigBit O = mapped_cell->getPort(ID(o));
1276 if (I.wire)
1277 I.wire = module->wires_.at(remap_name(I.wire->name));
1278 log_assert(O.wire);
1279 O.wire = module->wires_.at(remap_name(O.wire->name));
1280 module->connect(O, I);
1281 continue;
1282 }
1283
1284 RTLIL::Module* box_module = design->module(existing_cell->type);
1285 log_assert(existing_cell->parameters.empty());
1286 log_assert(mapped_cell->type == stringf("$__boxid%d", box_module->attributes.at(ID::abc9_box_id).as_int()));
1287 mapped_cell->type = existing_cell->type;
1288
1289 RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
1290 cell->parameters = existing_cell->parameters;
1291 cell->attributes = existing_cell->attributes;
1292 module->swap_names(cell, existing_cell);
1293
1294 auto jt = mapped_cell->connections_.find(ID(i));
1295 log_assert(jt != mapped_cell->connections_.end());
1296 SigSpec inputs = std::move(jt->second);
1297 mapped_cell->connections_.erase(jt);
1298 jt = mapped_cell->connections_.find(ID(o));
1299 log_assert(jt != mapped_cell->connections_.end());
1300 SigSpec outputs = std::move(jt->second);
1301 mapped_cell->connections_.erase(jt);
1302
1303 auto abc9_flop = box_module->get_bool_attribute(ID::abc9_flop);
1304 if (!abc9_flop) {
1305 for (const auto &i : inputs)
1306 bit_users[i].insert(mapped_cell->name);
1307 for (const auto &i : outputs)
1308 // Ignore inouts for topo ordering
1309 if (i.wire && !(i.wire->port_input && i.wire->port_output))
1310 bit_drivers[i].insert(mapped_cell->name);
1311 }
1312
1313 int input_count = 0, output_count = 0;
1314 for (const auto &port_name : box_ports.at(existing_cell->type)) {
1315 RTLIL::Wire *w = box_module->wire(port_name);
1316 log_assert(w);
1317
1318 SigSpec sig;
1319 if (w->port_input) {
1320 sig = inputs.extract(input_count, GetSize(w));
1321 input_count += GetSize(w);
1322 }
1323 if (w->port_output) {
1324 sig = outputs.extract(output_count, GetSize(w));
1325 output_count += GetSize(w);
1326 }
1327
1328 SigSpec newsig;
1329 for (auto c : sig.chunks()) {
1330 if (c.width == 0)
1331 continue;
1332 //log_assert(c.width == 1);
1333 if (c.wire)
1334 c.wire = module->wires_.at(remap_name(c.wire->name));
1335 newsig.append(c);
1336 }
1337 cell->setPort(port_name, newsig);
1338
1339 if (w->port_input && !abc9_flop)
1340 for (const auto &i : newsig)
1341 bit2sinks[i].push_back(cell);
1342 }
1343 }
1344
1345 cell_stats[mapped_cell->type]++;
1346 }
1347
1348 for (auto cell : boxes)
1349 module->remove(cell);
1350
1351 // Copy connections (and rename) from mapped_mod to module
1352 for (auto conn : mapped_mod->connections()) {
1353 if (!conn.first.is_fully_const()) {
1354 auto chunks = conn.first.chunks();
1355 for (auto &c : chunks)
1356 c.wire = module->wires_.at(remap_name(c.wire->name));
1357 conn.first = std::move(chunks);
1358 }
1359 if (!conn.second.is_fully_const()) {
1360 auto chunks = conn.second.chunks();
1361 for (auto &c : chunks)
1362 if (c.wire)
1363 c.wire = module->wires_.at(remap_name(c.wire->name));
1364 conn.second = std::move(chunks);
1365 }
1366 module->connect(conn);
1367 }
1368
1369 for (auto &it : cell_stats)
1370 log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second);
1371 int in_wires = 0, out_wires = 0;
1372
1373 // Stitch in mapped_mod's inputs/outputs into module
1374 for (auto port : mapped_mod->ports) {
1375 RTLIL::Wire *mapped_wire = mapped_mod->wire(port);
1376 RTLIL::Wire *wire = module->wire(port);
1377 log_assert(wire);
1378 wire->attributes.erase(ID::abc9_keep);
1379
1380 RTLIL::Wire *remap_wire = module->wire(remap_name(port));
1381 RTLIL::SigSpec signal(wire, remap_wire->start_offset-wire->start_offset, GetSize(remap_wire));
1382 log_assert(GetSize(signal) >= GetSize(remap_wire));
1383
1384 RTLIL::SigSig conn;
1385 if (mapped_wire->port_output) {
1386 conn.first = signal;
1387 conn.second = remap_wire;
1388 out_wires++;
1389 module->connect(conn);
1390 }
1391 else if (mapped_wire->port_input) {
1392 conn.first = remap_wire;
1393 conn.second = signal;
1394 in_wires++;
1395 module->connect(conn);
1396 }
1397 }
1398
1399 // ABC9 will return $_NOT_ gates in its mapping (since they are
1400 // treated as being "free"), in particular driving primary
1401 // outputs (real primary outputs, or cells treated as blackboxes)
1402 // or driving box inputs.
1403 // Instead of just mapping those $_NOT_ gates into 2-input $lut-s
1404 // at an area and delay cost, see if it is possible to push
1405 // this $_NOT_ into the driving LUT, or into all sink LUTs.
1406 // When this is not possible, (i.e. this signal drives two primary
1407 // outputs, only one of which is complemented) and when the driver
1408 // is a LUT, then clone the LUT so that it can be inverted without
1409 // increasing depth/delay.
1410 for (auto &it : bit_users)
1411 if (bit_drivers.count(it.first))
1412 for (auto driver_cell : bit_drivers.at(it.first))
1413 for (auto user_cell : it.second)
1414 toposort.edge(driver_cell, user_cell);
1415 bool no_loops YS_ATTRIBUTE(unused) = toposort.sort();
1416 log_assert(no_loops);
1417
1418 for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) {
1419 RTLIL::Cell *not_cell = mapped_mod->cell(*ii);
1420 log_assert(not_cell);
1421 if (not_cell->type != ID($_NOT_))
1422 continue;
1423 auto it = not2drivers.find(not_cell);
1424 if (it == not2drivers.end())
1425 continue;
1426 RTLIL::Cell *driver_lut = it->second;
1427 RTLIL::SigBit a_bit = not_cell->getPort(ID::A);
1428 RTLIL::SigBit y_bit = not_cell->getPort(ID::Y);
1429 RTLIL::Const driver_mask;
1430
1431 a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name));
1432 y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name));
1433
1434 auto jt = bit2sinks.find(a_bit);
1435 if (jt == bit2sinks.end())
1436 goto clone_lut;
1437
1438 for (auto sink_cell : jt->second)
1439 if (sink_cell->type != ID($lut))
1440 goto clone_lut;
1441
1442 // Push downstream LUTs past inverter
1443 for (auto sink_cell : jt->second) {
1444 SigSpec A = sink_cell->getPort(ID::A);
1445 RTLIL::Const mask = sink_cell->getParam(ID::LUT);
1446 int index = 0;
1447 for (; index < GetSize(A); index++)
1448 if (A[index] == a_bit)
1449 break;
1450 log_assert(index < GetSize(A));
1451 int i = 0;
1452 while (i < GetSize(mask)) {
1453 for (int j = 0; j < (1 << index); j++)
1454 std::swap(mask[i+j], mask[i+j+(1 << index)]);
1455 i += 1 << (index+1);
1456 }
1457 A[index] = y_bit;
1458 sink_cell->setPort(ID::A, A);
1459 sink_cell->setParam(ID::LUT, mask);
1460 }
1461
1462 // Since we have rewritten all sinks (which we know
1463 // to be only LUTs) to be after the inverter, we can
1464 // go ahead and clone the LUT with the expectation
1465 // that the original driving LUT will become dangling
1466 // and get cleaned away
1467 clone_lut:
1468 driver_mask = driver_lut->getParam(ID::LUT);
1469 for (auto &b : driver_mask.bits) {
1470 if (b == RTLIL::State::S0) b = RTLIL::State::S1;
1471 else if (b == RTLIL::State::S1) b = RTLIL::State::S0;
1472 }
1473 auto cell = module->addLut(NEW_ID,
1474 driver_lut->getPort(ID::A),
1475 y_bit,
1476 driver_mask);
1477 for (auto &bit : cell->connections_.at(ID::A)) {
1478 bit.wire = module->wires_.at(remap_name(bit.wire->name));
1479 bit2sinks[bit].push_back(cell);
1480 }
1481 }
1482
1483 //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires);
1484 log("ABC RESULTS: input signals: %8d\n", in_wires);
1485 log("ABC RESULTS: output signals: %8d\n", out_wires);
1486
1487 design->remove(mapped_mod);
1488 }
1489
1490 struct Abc9OpsPass : public Pass {
1491 Abc9OpsPass() : Pass("abc9_ops", "helper functions for ABC9") { }
1492 void help() YS_OVERRIDE
1493 {
1494 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
1495 log("\n");
1496 log(" abc9_ops [options] [selection]\n");
1497 log("\n");
1498 log("This pass contains a set of supporting operations for use during ABC technology\n");
1499 log("mapping, and is expected to be called in conjunction with other operations from\n");
1500 log("the `abc9' script pass. Only fully-selected modules are supported.\n");
1501 log("\n");
1502 log(" -check\n");
1503 log(" check that the design is valid, e.g. (* abc9_box_id *) values are unique,\n");
1504 log(" (* abc9_carry *) is only given for one input/output port, etc.\n");
1505 log("\n");
1506 log(" -prep_hier\n");
1507 log(" derive all used (* abc9_box *) or (* abc9_flop *) (if -dff option)\n");
1508 log(" whitebox modules. with (* abc9_flop *) modules, only those containing\n");
1509 log(" $dff/$_DFF_[NP]_ cells with zero initial state -- due to an ABC limitation\n");
1510 log(" -- will be derived.\n");
1511 log("\n");
1512 log(" -prep_bypass\n");
1513 log(" create techmap rules in the '$abc9_map' and '$abc9_unmap' designs for\n");
1514 log(" bypassing sequential (* abc9_box *) modules using a combinatorial box\n");
1515 log(" (named *_$abc9_byp). bypassing is necessary if sequential elements (e.g.\n");
1516 log(" $dff, $mem, etc.) are discovered inside so that any combinatorial paths\n");
1517 log(" will be correctly captured. this bypass box will only contain ports that\n");
1518 log(" are referenced by a simple path declaration ($specify2 cell) inside a\n");
1519 log(" specify block.\n");
1520 log("\n");
1521 log(" -prep_dff\n");
1522 log(" select all (* abc9_flop *) modules instantiated in the design and store\n");
1523 log(" in the named selection '$abc9_flops'.\n");
1524 log("\n");
1525 log(" -prep_dff_submod\n");
1526 log(" within (* abc9_flop *) modules, rewrite all edge-sensitive path\n");
1527 log(" declarations and $setup() timing checks ($specify3 and $specrule cells)\n");
1528 log(" that share a 'DST' port with the $_DFF_[NP]_.Q port from this 'Q' port to\n");
1529 log(" the DFF's 'D' port. this is to prepare such specify cells to be moved\n");
1530 log(" into the flop box.\n");
1531 log("\n");
1532 log(" -prep_dff_unmap\n");
1533 log(" populate the '$abc9_unmap' design with techmap rules for mapping *_$abc9_flop\n");
1534 log(" cells back into their derived cell types (where the rules created by\n");
1535 log(" -prep_hier will then map back to the original cell with parameters).\n");
1536 log("\n");
1537 log(" -prep_delays\n");
1538 log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n");
1539 log(" certain required times.\n");
1540 log("\n");
1541 log(" -mark_scc\n");
1542 log(" for an arbitrarily chosen cell in each unique SCC of each selected module\n");
1543 log(" (tagged with an (* abc9_scc_id = <int> *) attribute), temporarily mark all\n");
1544 log(" wires driven by this cell's outputs with a (* keep *) attribute in order\n");
1545 log(" to break the SCC. this temporary attribute will be removed on -reintegrate.\n");
1546 log("\n");
1547 log(" -prep_xaiger\n");
1548 log(" prepare the design for XAIGER output. this includes computing the\n");
1549 log(" topological ordering of ABC9 boxes, as well as preparing the '$abc9_holes'\n");
1550 log(" design that contains the logic behaviour of ABC9 whiteboxes.\n");
1551 log("\n");
1552 log(" -dff\n");
1553 log(" consider flop cells (those instantiating modules marked with (* abc9_flop *))\n");
1554 log(" during -prep_{delays,xaiger,box}.\n");
1555 log("\n");
1556 log(" -prep_lut <maxlut>\n");
1557 log(" pre-compute the lut library by analysing all modules marked with\n");
1558 log(" (* abc9_lut=<area> *).\n");
1559 log("\n");
1560 log(" -write_lut <dst>\n");
1561 log(" write the pre-computed lut library to <dst>.\n");
1562 log("\n");
1563 log(" -prep_box\n");
1564 log(" pre-compute the box library by analysing all modules marked with\n");
1565 log(" (* abc9_box *).\n");
1566 log("\n");
1567 log(" -write_box <dst>\n");
1568 log(" write the pre-computed box library to <dst>.\n");
1569 log("\n");
1570 log(" -reintegrate\n");
1571 log(" for each selected module, re-intergrate the module '<module-name>$abc9'\n");
1572 log(" by first recovering ABC9 boxes, and then stitching in the remaining primary\n");
1573 log(" inputs and outputs.\n");
1574 log("\n");
1575 }
1576 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
1577 {
1578 log_header(design, "Executing ABC9_OPS pass (helper functions for ABC9).\n");
1579
1580 bool check_mode = false;
1581 bool prep_delays_mode = false;
1582 bool mark_scc_mode = false;
1583 bool prep_hier_mode = false;
1584 bool prep_bypass_mode = false;
1585 bool prep_dff_mode = false, prep_dff_submod_mode = false, prep_dff_unmap_mode = false;
1586 bool prep_xaiger_mode = false;
1587 bool prep_lut_mode = false;
1588 bool prep_box_mode = false;
1589 bool reintegrate_mode = false;
1590 bool dff_mode = false;
1591 std::string write_lut_dst;
1592 int maxlut = 0;
1593 std::string write_box_dst;
1594
1595 bool valid = false;
1596 size_t argidx;
1597 for (argidx = 1; argidx < args.size(); argidx++) {
1598 std::string arg = args[argidx];
1599 if (arg == "-check") {
1600 check_mode = true;
1601 valid = true;
1602 continue;
1603 }
1604 if (arg == "-mark_scc") {
1605 mark_scc_mode = true;
1606 valid = true;
1607 continue;
1608 }
1609 if (arg == "-prep_hier") {
1610 prep_hier_mode = true;
1611 valid = true;
1612 continue;
1613 }
1614 if (arg == "-prep_bypass") {
1615 prep_bypass_mode = true;
1616 valid = true;
1617 continue;
1618 }
1619 if (arg == "-prep_dff") {
1620 prep_dff_mode = true;
1621 valid = true;
1622 continue;
1623 }
1624 if (arg == "-prep_dff_submod") {
1625 prep_dff_submod_mode = true;
1626 valid = true;
1627 continue;
1628 }
1629 if (arg == "-prep_dff_unmap") {
1630 prep_dff_unmap_mode = true;
1631 valid = true;
1632 continue;
1633 }
1634 if (arg == "-prep_xaiger") {
1635 prep_xaiger_mode = true;
1636 valid = true;
1637 continue;
1638 }
1639 if (arg == "-prep_delays") {
1640 prep_delays_mode = true;
1641 valid = true;
1642 continue;
1643 }
1644 if (arg == "-prep_lut" && argidx+1 < args.size()) {
1645 prep_lut_mode = true;
1646 maxlut = atoi(args[++argidx].c_str());
1647 valid = true;
1648 continue;
1649 }
1650 if (arg == "-write_lut" && argidx+1 < args.size()) {
1651 write_lut_dst = args[++argidx];
1652 rewrite_filename(write_lut_dst);
1653 valid = true;
1654 continue;
1655 }
1656 if (arg == "-prep_box") {
1657 prep_box_mode = true;
1658 valid = true;
1659 continue;
1660 }
1661 if (arg == "-write_box" && argidx+1 < args.size()) {
1662 write_box_dst = args[++argidx];
1663 rewrite_filename(write_box_dst);
1664 valid = true;
1665 continue;
1666 }
1667 if (arg == "-reintegrate") {
1668 reintegrate_mode = true;
1669 valid = true;
1670 continue;
1671 }
1672 if (arg == "-dff") {
1673 dff_mode = true;
1674 continue;
1675 }
1676 break;
1677 }
1678 extra_args(args, argidx, design);
1679
1680 if (!valid)
1681 log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate must be specified.\n");
1682
1683 if (dff_mode && !check_mode && !prep_hier_mode && !prep_delays_mode && !prep_xaiger_mode && !reintegrate_mode)
1684 log_cmd_error("'-dff' option is only relevant for -prep_{hier,delay,xaiger} or -reintegrate.\n");
1685
1686 if (check_mode)
1687 check(design, dff_mode);
1688 if (prep_hier_mode)
1689 prep_hier(design, dff_mode);
1690 if (prep_bypass_mode)
1691 prep_bypass(design);
1692 if (prep_dff_mode)
1693 prep_dff(design);
1694 if (prep_dff_submod_mode)
1695 prep_dff_submod(design);
1696 if (prep_dff_unmap_mode)
1697 prep_dff_unmap(design);
1698 if (prep_delays_mode)
1699 prep_delays(design, dff_mode);
1700 if (prep_lut_mode)
1701 prep_lut(design, maxlut);
1702 if (prep_box_mode)
1703 prep_box(design);
1704
1705 for (auto mod : design->selected_modules()) {
1706 if (mod->processes.size() > 0) {
1707 log("Skipping module %s as it contains processes.\n", log_id(mod));
1708 continue;
1709 }
1710
1711 if (!design->selected_whole_module(mod))
1712 log_error("Can't handle partially selected module %s!\n", log_id(mod));
1713
1714 if (!write_lut_dst.empty())
1715 write_lut(mod, write_lut_dst);
1716 if (!write_box_dst.empty())
1717 write_box(mod, write_box_dst);
1718 if (mark_scc_mode)
1719 mark_scc(mod);
1720 if (prep_xaiger_mode)
1721 prep_xaiger(mod, dff_mode);
1722 if (reintegrate_mode)
1723 reintegrate(mod, dff_mode);
1724 }
1725 }
1726 } Abc9OpsPass;
1727
1728 PRIVATE_NAMESPACE_END