Transform all "\\*" identifiers into ID()
[yosys.git] / passes / techmap / muxcover.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
22
23 USING_YOSYS_NAMESPACE
24 PRIVATE_NAMESPACE_BEGIN
25
26 #define COST_DMUX 90
27 #define COST_MUX2 100
28 #define COST_MUX4 220
29 #define COST_MUX8 460
30 #define COST_MUX16 940
31
32 struct MuxcoverWorker
33 {
34 Module *module;
35 SigMap sigmap;
36
37 struct newmux_t
38 {
39 int cost;
40 vector<SigBit> inputs, selects;
41 newmux_t() : cost(0) {}
42 };
43
44 struct tree_t
45 {
46 SigBit root;
47 dict<SigBit, Cell*> muxes;
48 dict<SigBit, newmux_t> newmuxes;
49 };
50
51 vector<tree_t> tree_list;
52
53 dict<tuple<SigBit, SigBit, SigBit>, tuple<SigBit, pool<SigBit>, bool>> decode_mux_cache;
54 dict<SigBit, tuple<SigBit, SigBit, SigBit>> decode_mux_reverse_cache;
55 int decode_mux_counter;
56
57 bool use_mux4;
58 bool use_mux8;
59 bool use_mux16;
60 bool nodecode;
61 bool nopartial;
62
63 int cost_dmux;
64 int cost_mux2;
65 int cost_mux4;
66 int cost_mux8;
67 int cost_mux16;
68
69 MuxcoverWorker(Module *module) : module(module), sigmap(module)
70 {
71 use_mux4 = false;
72 use_mux8 = false;
73 use_mux16 = false;
74 nodecode = false;
75 nopartial = false;
76 cost_dmux = COST_DMUX;
77 cost_mux2 = COST_MUX2;
78 cost_mux4 = COST_MUX4;
79 cost_mux8 = COST_MUX8;
80 cost_mux16 = COST_MUX16;
81 decode_mux_counter = 0;
82 }
83
84 bool xcmp(std::initializer_list<SigBit> list)
85 {
86 auto cursor = list.begin(), end = list.end();
87 log_assert(cursor != end);
88 SigBit tmp = *(cursor++);
89 while (cursor != end) {
90 SigBit bit = *(cursor++);
91 if (bit == State::Sx)
92 continue;
93 if (tmp == State::Sx)
94 tmp = bit;
95 if (bit != tmp)
96 return false;
97 }
98 return true;
99 }
100
101 void treeify()
102 {
103 pool<SigBit> roots;
104 pool<SigBit> used_once;
105 dict<SigBit, Cell*> sig_to_mux;
106
107 for (auto wire : module->wires()) {
108 if (!wire->port_output)
109 continue;
110 for (auto bit : sigmap(wire))
111 roots.insert(bit);
112 }
113
114 for (auto cell : module->cells()) {
115 for (auto conn : cell->connections()) {
116 if (!cell->input(conn.first))
117 continue;
118 for (auto bit : sigmap(conn.second)) {
119 if (used_once.count(bit) || cell->type != ID($_MUX_) || conn.first == ID(\\S))
120 roots.insert(bit);
121 used_once.insert(bit);
122 }
123 }
124 if (cell->type == ID($_MUX_))
125 sig_to_mux[sigmap(cell->getPort(ID(\\Y)))] = cell;
126 }
127
128 log(" Treeifying %d MUXes:\n", GetSize(sig_to_mux));
129
130 roots.sort();
131 for (auto rootsig : roots)
132 {
133 tree_t tree;
134 tree.root = rootsig;
135
136 pool<SigBit> wavefront;
137 wavefront.insert(rootsig);
138
139 while (!wavefront.empty()) {
140 SigBit bit = wavefront.pop();
141 if (sig_to_mux.count(bit) && (bit == rootsig || !roots.count(bit))) {
142 Cell *c = sig_to_mux.at(bit);
143 tree.muxes[bit] = c;
144 wavefront.insert(sigmap(c->getPort(ID(\\A))));
145 wavefront.insert(sigmap(c->getPort(ID(\\B))));
146 }
147 }
148
149 if (!tree.muxes.empty()) {
150 log(" Found tree with %d MUXes at root %s.\n", GetSize(tree.muxes), log_signal(tree.root));
151 tree_list.push_back(tree);
152 }
153 }
154
155 log(" Finished treeification: Found %d trees.\n", GetSize(tree_list));
156 }
157
158 bool follow_muxtree(SigBit &ret_bit, tree_t &tree, SigBit bit, const char *path, bool first_layer = true)
159 {
160 if (*path) {
161 if (tree.muxes.count(bit) == 0) {
162 if (first_layer || nopartial)
163 return false;
164 while (path[0] && path[1])
165 path++;
166 if (path[0] == 'S')
167 ret_bit = State::Sx;
168 else
169 ret_bit = bit;
170 return true;
171 }
172 char port_name[3] = {'\\', *path, 0};
173 return follow_muxtree(ret_bit, tree, sigmap(tree.muxes.at(bit)->getPort(port_name)), path+1, false);
174 } else {
175 ret_bit = bit;
176 return true;
177 }
178 }
179
180 int prepare_decode_mux(SigBit &A, SigBit B, SigBit sel, SigBit bit)
181 {
182 if (A == B || sel == State::Sx)
183 return 0;
184
185 tuple<SigBit, SigBit, SigBit> key(A, B, sel);
186 if (decode_mux_cache.count(key) == 0) {
187 auto &entry = decode_mux_cache[key];
188 std::get<0>(entry) = module->addWire(NEW_ID);
189 std::get<2>(entry) = false;
190 decode_mux_reverse_cache[std::get<0>(entry)] = key;
191 }
192
193 auto &entry = decode_mux_cache[key];
194 A = std::get<0>(entry);
195 std::get<1>(entry).insert(bit);
196
197 if (std::get<2>(entry))
198 return 0;
199
200 if (A == State::Sx || B == State::Sx)
201 return 0;
202
203 return cost_dmux / GetSize(std::get<1>(entry));
204 }
205
206 void implement_decode_mux(SigBit ctrl_bit)
207 {
208 if (decode_mux_reverse_cache.count(ctrl_bit) == 0)
209 return;
210
211 auto &key = decode_mux_reverse_cache.at(ctrl_bit);
212 auto &entry = decode_mux_cache[key];
213
214 if (std::get<2>(entry))
215 return;
216
217 implement_decode_mux(std::get<0>(key));
218 implement_decode_mux(std::get<1>(key));
219
220 if (std::get<0>(key) == State::Sx) {
221 module->addBufGate(NEW_ID, std::get<1>(key), ctrl_bit);
222 } else if (std::get<1>(key) == State::Sx) {
223 module->addBufGate(NEW_ID, std::get<0>(key), ctrl_bit);
224 } else {
225 module->addMuxGate(NEW_ID, std::get<0>(key), std::get<1>(key), std::get<2>(key), ctrl_bit);
226 decode_mux_counter++;
227 }
228 std::get<2>(entry) = true;
229 }
230
231 void find_best_covers(tree_t &tree, const vector<SigBit> &bits)
232 {
233 for (auto bit : bits)
234 find_best_cover(tree, bit);
235 }
236
237 int sum_best_covers(tree_t &tree, const vector<SigBit> &bits)
238 {
239 int sum = 0;
240 for (auto bit : pool<SigBit>(bits.begin(), bits.end())) {
241 int cost = tree.newmuxes.at(bit).cost;
242 log_debug(" Best cost for %s: %d\n", log_signal(bit), cost);
243 sum += cost;
244 }
245 return sum;
246 }
247
248 int find_best_cover(tree_t &tree, SigBit bit)
249 {
250 if (tree.newmuxes.count(bit)) {
251 return tree.newmuxes.at(bit).cost;
252 }
253
254 SigBit A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P;
255 SigBit S1, S2, S3, S4, S5, S6, S7, S8;
256 SigBit T1, T2, T3, T4;
257 SigBit U1, U2;
258 SigBit V1;
259
260 newmux_t best_mux;
261 bool ok = true;
262
263 // 2-Input MUX
264
265 ok = ok && follow_muxtree(A, tree, bit, "A");
266 ok = ok && follow_muxtree(B, tree, bit, "B");
267
268 ok = ok && follow_muxtree(S1, tree, bit, "S");
269
270 if (ok)
271 {
272 newmux_t mux;
273
274 mux.inputs.push_back(A);
275 mux.inputs.push_back(B);
276 mux.selects.push_back(S1);
277
278 find_best_covers(tree, mux.inputs);
279 log_debug(" Decode cost for mux2 at %s: %d\n", log_signal(bit), mux.cost);
280
281 mux.cost += cost_mux2;
282 mux.cost += sum_best_covers(tree, mux.inputs);
283
284 log_debug(" Cost of mux2 at %s: %d\n", log_signal(bit), mux.cost);
285
286 best_mux = mux;
287 }
288
289 // 4-Input MUX
290
291 if (use_mux4)
292 {
293 ok = ok && follow_muxtree(A, tree, bit, "AA");
294 ok = ok && follow_muxtree(B, tree, bit, "AB");
295 ok = ok && follow_muxtree(C, tree, bit, "BA");
296 ok = ok && follow_muxtree(D, tree, bit, "BB");
297
298 ok = ok && follow_muxtree(S1, tree, bit, "AS");
299 ok = ok && follow_muxtree(S2, tree, bit, "BS");
300
301 if (nodecode)
302 ok = ok && xcmp({S1, S2});
303
304 ok = ok && follow_muxtree(T1, tree, bit, "S");
305
306 if (ok)
307 {
308 newmux_t mux;
309
310 mux.inputs.push_back(A);
311 mux.inputs.push_back(B);
312 mux.inputs.push_back(C);
313 mux.inputs.push_back(D);
314
315 mux.cost += prepare_decode_mux(S1, S2, T1, bit);
316
317 mux.selects.push_back(S1);
318 mux.selects.push_back(T1);
319
320 find_best_covers(tree, mux.inputs);
321 log_debug(" Decode cost for mux4 at %s: %d\n", log_signal(bit), mux.cost);
322
323 mux.cost += cost_mux4;
324 mux.cost += sum_best_covers(tree, mux.inputs);
325
326 log_debug(" Cost of mux4 at %s: %d\n", log_signal(bit), mux.cost);
327
328 if (best_mux.cost >= mux.cost)
329 best_mux = mux;
330 }
331 }
332
333 // 8-Input MUX
334
335 if (use_mux8)
336 {
337 ok = ok && follow_muxtree(A, tree, bit, "AAA");
338 ok = ok && follow_muxtree(B, tree, bit, "AAB");
339 ok = ok && follow_muxtree(C, tree, bit, "ABA");
340 ok = ok && follow_muxtree(D, tree, bit, "ABB");
341 ok = ok && follow_muxtree(E, tree, bit, "BAA");
342 ok = ok && follow_muxtree(F, tree, bit, "BAB");
343 ok = ok && follow_muxtree(G, tree, bit, "BBA");
344 ok = ok && follow_muxtree(H, tree, bit, "BBB");
345
346 ok = ok && follow_muxtree(S1, tree, bit, "AAS");
347 ok = ok && follow_muxtree(S2, tree, bit, "ABS");
348 ok = ok && follow_muxtree(S3, tree, bit, "BAS");
349 ok = ok && follow_muxtree(S4, tree, bit, "BBS");
350
351 if (nodecode)
352 ok = ok && xcmp({S1, S2, S3, S4});
353
354 ok = ok && follow_muxtree(T1, tree, bit, "AS");
355 ok = ok && follow_muxtree(T2, tree, bit, "BS");
356
357 if (nodecode)
358 ok = ok && xcmp({T1, T2});
359
360 ok = ok && follow_muxtree(U1, tree, bit, "S");
361
362 if (ok)
363 {
364 newmux_t mux;
365
366 mux.inputs.push_back(A);
367 mux.inputs.push_back(B);
368 mux.inputs.push_back(C);
369 mux.inputs.push_back(D);
370 mux.inputs.push_back(E);
371 mux.inputs.push_back(F);
372 mux.inputs.push_back(G);
373 mux.inputs.push_back(H);
374
375 mux.cost += prepare_decode_mux(S1, S2, T1, bit);
376 mux.cost += prepare_decode_mux(S3, S4, T2, bit);
377 mux.cost += prepare_decode_mux(S1, S3, U1, bit);
378
379 mux.cost += prepare_decode_mux(T1, T2, U1, bit);
380
381 mux.selects.push_back(S1);
382 mux.selects.push_back(T1);
383 mux.selects.push_back(U1);
384
385 find_best_covers(tree, mux.inputs);
386 log_debug(" Decode cost for mux8 at %s: %d\n", log_signal(bit), mux.cost);
387
388 mux.cost += cost_mux8;
389 mux.cost += sum_best_covers(tree, mux.inputs);
390
391 log_debug(" Cost of mux8 at %s: %d\n", log_signal(bit), mux.cost);
392
393 if (best_mux.cost >= mux.cost)
394 best_mux = mux;
395 }
396 }
397
398 // 16-Input MUX
399
400 if (use_mux16)
401 {
402 ok = ok && follow_muxtree(A, tree, bit, "AAAA");
403 ok = ok && follow_muxtree(B, tree, bit, "AAAB");
404 ok = ok && follow_muxtree(C, tree, bit, "AABA");
405 ok = ok && follow_muxtree(D, tree, bit, "AABB");
406 ok = ok && follow_muxtree(E, tree, bit, "ABAA");
407 ok = ok && follow_muxtree(F, tree, bit, "ABAB");
408 ok = ok && follow_muxtree(G, tree, bit, "ABBA");
409 ok = ok && follow_muxtree(H, tree, bit, "ABBB");
410 ok = ok && follow_muxtree(I, tree, bit, "BAAA");
411 ok = ok && follow_muxtree(J, tree, bit, "BAAB");
412 ok = ok && follow_muxtree(K, tree, bit, "BABA");
413 ok = ok && follow_muxtree(L, tree, bit, "BABB");
414 ok = ok && follow_muxtree(M, tree, bit, "BBAA");
415 ok = ok && follow_muxtree(N, tree, bit, "BBAB");
416 ok = ok && follow_muxtree(O, tree, bit, "BBBA");
417 ok = ok && follow_muxtree(P, tree, bit, "BBBB");
418
419 ok = ok && follow_muxtree(S1, tree, bit, "AAAS");
420 ok = ok && follow_muxtree(S2, tree, bit, "AABS");
421 ok = ok && follow_muxtree(S3, tree, bit, "ABAS");
422 ok = ok && follow_muxtree(S4, tree, bit, "ABBS");
423 ok = ok && follow_muxtree(S5, tree, bit, "BAAS");
424 ok = ok && follow_muxtree(S6, tree, bit, "BABS");
425 ok = ok && follow_muxtree(S7, tree, bit, "BBAS");
426 ok = ok && follow_muxtree(S8, tree, bit, "BBBS");
427
428 if (nodecode)
429 ok = ok && xcmp({S1, S2, S3, S4, S5, S6, S7, S8});
430
431 ok = ok && follow_muxtree(T1, tree, bit, "AAS");
432 ok = ok && follow_muxtree(T2, tree, bit, "ABS");
433 ok = ok && follow_muxtree(T3, tree, bit, "BAS");
434 ok = ok && follow_muxtree(T4, tree, bit, "BBS");
435
436 if (nodecode)
437 ok = ok && xcmp({T1, T2, T3, T4});
438
439 ok = ok && follow_muxtree(U1, tree, bit, "AS");
440 ok = ok && follow_muxtree(U2, tree, bit, "BS");
441
442 if (nodecode)
443 ok = ok && xcmp({U1, U2});
444
445 ok = ok && follow_muxtree(V1, tree, bit, "S");
446
447 if (ok)
448 {
449 newmux_t mux;
450
451 mux.inputs.push_back(A);
452 mux.inputs.push_back(B);
453 mux.inputs.push_back(C);
454 mux.inputs.push_back(D);
455 mux.inputs.push_back(E);
456 mux.inputs.push_back(F);
457 mux.inputs.push_back(G);
458 mux.inputs.push_back(H);
459 mux.inputs.push_back(I);
460 mux.inputs.push_back(J);
461 mux.inputs.push_back(K);
462 mux.inputs.push_back(L);
463 mux.inputs.push_back(M);
464 mux.inputs.push_back(N);
465 mux.inputs.push_back(O);
466 mux.inputs.push_back(P);
467
468 mux.cost += prepare_decode_mux(S1, S2, T1, bit);
469 mux.cost += prepare_decode_mux(S3, S4, T2, bit);
470 mux.cost += prepare_decode_mux(S5, S6, T3, bit);
471 mux.cost += prepare_decode_mux(S7, S8, T4, bit);
472 mux.cost += prepare_decode_mux(S1, S3, U1, bit);
473 mux.cost += prepare_decode_mux(S5, S7, U2, bit);
474 mux.cost += prepare_decode_mux(S1, S5, V1, bit);
475
476 mux.cost += prepare_decode_mux(T1, T2, U1, bit);
477 mux.cost += prepare_decode_mux(T3, T4, U2, bit);
478 mux.cost += prepare_decode_mux(T1, T3, V1, bit);
479
480 mux.cost += prepare_decode_mux(U1, U2, V1, bit);
481
482 mux.selects.push_back(S1);
483 mux.selects.push_back(T1);
484 mux.selects.push_back(U1);
485 mux.selects.push_back(V1);
486
487 find_best_covers(tree, mux.inputs);
488 log_debug(" Decode cost for mux16 at %s: %d\n", log_signal(bit), mux.cost);
489
490 mux.cost += cost_mux16;
491 mux.cost += sum_best_covers(tree, mux.inputs);
492
493 log_debug(" Cost of mux16 at %s: %d\n", log_signal(bit), mux.cost);
494
495 if (best_mux.cost >= mux.cost)
496 best_mux = mux;
497 }
498 }
499
500 tree.newmuxes[bit] = best_mux;
501 return best_mux.cost;
502 }
503
504 void implement_best_cover(tree_t &tree, SigBit bit, int count_muxes_by_type[4])
505 {
506 newmux_t mux = tree.newmuxes.at(bit);
507
508 for (auto inbit : mux.inputs)
509 implement_best_cover(tree, inbit, count_muxes_by_type);
510
511 for (auto selbit : mux.selects)
512 implement_decode_mux(selbit);
513
514 if (GetSize(mux.inputs) == 0)
515 return;
516
517 if (GetSize(mux.inputs) == 2) {
518 count_muxes_by_type[0]++;
519 Cell *cell = module->addCell(NEW_ID, ID($_MUX_));
520 cell->setPort(ID(\\A), mux.inputs[0]);
521 cell->setPort(ID(\\B), mux.inputs[1]);
522 cell->setPort(ID(\\S), mux.selects[0]);
523 cell->setPort(ID(\\Y), bit);
524 return;
525 }
526
527 if (GetSize(mux.inputs) == 4) {
528 count_muxes_by_type[1]++;
529 Cell *cell = module->addCell(NEW_ID, ID($_MUX4_));
530 cell->setPort(ID(\\A), mux.inputs[0]);
531 cell->setPort(ID(\\B), mux.inputs[1]);
532 cell->setPort(ID(\\C), mux.inputs[2]);
533 cell->setPort(ID(\\D), mux.inputs[3]);
534 cell->setPort(ID(\\S), mux.selects[0]);
535 cell->setPort(ID(\\T), mux.selects[1]);
536 cell->setPort(ID(\\Y), bit);
537 return;
538 }
539
540 if (GetSize(mux.inputs) == 8) {
541 count_muxes_by_type[2]++;
542 Cell *cell = module->addCell(NEW_ID, ID($_MUX8_));
543 cell->setPort(ID(\\A), mux.inputs[0]);
544 cell->setPort(ID(\\B), mux.inputs[1]);
545 cell->setPort(ID(\\C), mux.inputs[2]);
546 cell->setPort(ID(\\D), mux.inputs[3]);
547 cell->setPort(ID(\\E), mux.inputs[4]);
548 cell->setPort(ID(\\F), mux.inputs[5]);
549 cell->setPort(ID(\\G), mux.inputs[6]);
550 cell->setPort(ID(\\H), mux.inputs[7]);
551 cell->setPort(ID(\\S), mux.selects[0]);
552 cell->setPort(ID(\\T), mux.selects[1]);
553 cell->setPort(ID(\\U), mux.selects[2]);
554 cell->setPort(ID(\\Y), bit);
555 return;
556 }
557
558 if (GetSize(mux.inputs) == 16) {
559 count_muxes_by_type[3]++;
560 Cell *cell = module->addCell(NEW_ID, ID($_MUX16_));
561 cell->setPort(ID(\\A), mux.inputs[0]);
562 cell->setPort(ID(\\B), mux.inputs[1]);
563 cell->setPort(ID(\\C), mux.inputs[2]);
564 cell->setPort(ID(\\D), mux.inputs[3]);
565 cell->setPort(ID(\\E), mux.inputs[4]);
566 cell->setPort(ID(\\F), mux.inputs[5]);
567 cell->setPort(ID(\\G), mux.inputs[6]);
568 cell->setPort(ID(\\H), mux.inputs[7]);
569 cell->setPort(ID(\\I), mux.inputs[8]);
570 cell->setPort(ID(\\J), mux.inputs[9]);
571 cell->setPort(ID(\\K), mux.inputs[10]);
572 cell->setPort(ID(\\L), mux.inputs[11]);
573 cell->setPort(ID(\\M), mux.inputs[12]);
574 cell->setPort(ID(\\N), mux.inputs[13]);
575 cell->setPort(ID(\\O), mux.inputs[14]);
576 cell->setPort(ID(\\P), mux.inputs[15]);
577 cell->setPort(ID(\\S), mux.selects[0]);
578 cell->setPort(ID(\\T), mux.selects[1]);
579 cell->setPort(ID(\\U), mux.selects[2]);
580 cell->setPort(ID(\\V), mux.selects[3]);
581 cell->setPort(ID(\\Y), bit);
582 return;
583 }
584
585 log_abort();
586 }
587
588 void treecover(tree_t &tree)
589 {
590 int count_muxes_by_type[4] = {0, 0, 0, 0};
591 log_debug(" Searching for best cover for tree at %s.\n", log_signal(tree.root));
592 find_best_cover(tree, tree.root);
593 implement_best_cover(tree, tree.root, count_muxes_by_type);
594 log(" Replaced tree at %s: %d MUX2, %d MUX4, %d MUX8, %d MUX16\n", log_signal(tree.root),
595 count_muxes_by_type[0], count_muxes_by_type[1], count_muxes_by_type[2], count_muxes_by_type[3]);
596 for (auto &it : tree.muxes)
597 module->remove(it.second);
598 }
599
600 void run()
601 {
602 log("Covering MUX trees in module %s..\n", log_id(module));
603
604 treeify();
605
606 log(" Covering trees:\n");
607
608 if (!nodecode) {
609 log_debug(" Populating cache of decoder muxes.\n");
610 for (auto &tree : tree_list) {
611 find_best_cover(tree, tree.root);
612 tree.newmuxes.clear();
613 }
614 }
615
616 for (auto &tree : tree_list)
617 treecover(tree);
618
619 if (!nodecode)
620 log(" Added a total of %d decoder MUXes.\n", decode_mux_counter);
621 }
622 };
623
624 struct MuxcoverPass : public Pass {
625 MuxcoverPass() : Pass("muxcover", "cover trees of MUX cells with wider MUXes") { }
626 void help() YS_OVERRIDE
627 {
628 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
629 log("\n");
630 log(" muxcover [options] [selection]\n");
631 log("\n");
632 log("Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells\n");
633 log("\n");
634 log(" -mux4[=cost], -mux8[=cost], -mux16[=cost]\n");
635 log(" Cover $_MUX_ trees using the specified types of MUXes (with optional\n");
636 log(" integer costs). If none of these options are given, the effect is the\n");
637 log(" same as if all of them are.\n");
638 log(" Default costs: $_MUX4_ = %d, $_MUX8_ = %d, \n", COST_MUX4, COST_MUX8);
639 log(" $_MUX16_ = %d\n", COST_MUX16);
640 log("\n");
641 log(" -mux2=cost\n");
642 log(" Use the specified cost for $_MUX_ cells when making covering decisions.\n");
643 log(" Default cost: $_MUX_ = %d\n", COST_MUX2);
644 log("\n");
645 log(" -dmux=cost\n");
646 log(" Use the specified cost for $_MUX_ cells used in decoders.\n");
647 log(" Default cost: %d\n", COST_DMUX);
648 log("\n");
649 log(" -nodecode\n");
650 log(" Do not insert decoder logic. This reduces the number of possible\n");
651 log(" substitutions, but guarantees that the resulting circuit is not\n");
652 log(" less efficient than the original circuit.\n");
653 log("\n");
654 log(" -nopartial\n");
655 log(" Do not consider mappings that use $_MUX<N>_ to select from less\n");
656 log(" than <N> different signals.\n");
657 log("\n");
658 }
659 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
660 {
661 log_header(design, "Executing MUXCOVER pass (mapping to wider MUXes).\n");
662
663 bool use_mux4 = false;
664 bool use_mux8 = false;
665 bool use_mux16 = false;
666 bool nodecode = false;
667 bool nopartial = false;
668 int cost_dmux = COST_DMUX;
669 int cost_mux2 = COST_MUX2;
670 int cost_mux4 = COST_MUX4;
671 int cost_mux8 = COST_MUX8;
672 int cost_mux16 = COST_MUX16;
673
674 size_t argidx;
675 for (argidx = 1; argidx < args.size(); argidx++)
676 {
677 const auto &arg = args[argidx];
678 if (arg.size() >= 6 && arg.compare(0,6,"-mux2=") == 0) {
679 cost_mux2 = atoi(arg.substr(6).c_str());
680 continue;
681 }
682 if (arg.size() >= 5 && arg.compare(0,5,"-mux4") == 0) {
683 use_mux4 = true;
684 if (arg.size() > 5) {
685 if (arg[5] != '=') break;
686 cost_mux4 = atoi(arg.substr(6).c_str());
687 }
688 continue;
689 }
690 if (arg.size() >= 5 && arg.compare(0,5,"-mux8") == 0) {
691 use_mux8 = true;
692 if (arg.size() > 5) {
693 if (arg[5] != '=') break;
694 cost_mux8 = atoi(arg.substr(6).c_str());
695 }
696 continue;
697 }
698 if (arg.size() >= 6 && arg.compare(0,6,"-mux16") == 0) {
699 use_mux16 = true;
700 if (arg.size() > 6) {
701 if (arg[6] != '=') break;
702 cost_mux16 = atoi(arg.substr(7).c_str());
703 }
704 continue;
705 }
706 if (arg.size() >= 6 && arg.compare(0,6,"-dmux=") == 0) {
707 cost_dmux = atoi(arg.substr(6).c_str());
708 continue;
709 }
710 if (arg == "-nodecode") {
711 nodecode = true;
712 continue;
713 }
714 if (arg == "-nopartial") {
715 nopartial = true;
716 continue;
717 }
718 break;
719 }
720 extra_args(args, argidx, design);
721
722 if (!use_mux4 && !use_mux8 && !use_mux16) {
723 use_mux4 = true;
724 use_mux8 = true;
725 use_mux16 = true;
726 }
727
728 for (auto module : design->selected_modules())
729 {
730 MuxcoverWorker worker(module);
731 worker.use_mux4 = use_mux4;
732 worker.use_mux8 = use_mux8;
733 worker.use_mux16 = use_mux16;
734 worker.cost_dmux = cost_dmux;
735 worker.cost_mux2 = cost_mux2;
736 worker.cost_mux4 = cost_mux4;
737 worker.cost_mux8 = cost_mux8;
738 worker.cost_mux16 = cost_mux16;
739 worker.nodecode = nodecode;
740 worker.nopartial = nopartial;
741 worker.run();
742 }
743 }
744 } MuxcoverPass;
745
746 PRIVATE_NAMESPACE_END