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