2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
24 PRIVATE_NAMESPACE_BEGIN
30 #define COST_MUX16 940
40 vector
<SigBit
> inputs
, selects
;
41 newmux_t() : cost(0) {}
47 dict
<SigBit
, Cell
*> muxes
;
48 dict
<SigBit
, newmux_t
> newmuxes
;
51 vector
<tree_t
> tree_list
;
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
;
69 MuxcoverWorker(Module
*module
) : module(module
), sigmap(module
)
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;
84 bool xcmp(std::initializer_list
<SigBit
> list
)
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
++);
104 pool
<SigBit
> used_once
;
105 dict
<SigBit
, Cell
*> sig_to_mux
;
107 for (auto wire
: module
->wires()) {
108 if (!wire
->port_output
)
110 for (auto bit
: sigmap(wire
))
114 for (auto cell
: module
->cells()) {
115 for (auto conn
: cell
->connections()) {
116 if (!cell
->input(conn
.first
))
118 for (auto bit
: sigmap(conn
.second
)) {
119 if (used_once
.count(bit
) || cell
->type
!= ID($_MUX_
) || conn
.first
== ID(\\S
))
121 used_once
.insert(bit
);
124 if (cell
->type
== ID($_MUX_
))
125 sig_to_mux
[sigmap(cell
->getPort(ID(\\Y
)))] = cell
;
128 log(" Treeifying %d MUXes:\n", GetSize(sig_to_mux
));
131 for (auto rootsig
: roots
)
136 pool
<SigBit
> wavefront
;
137 wavefront
.insert(rootsig
);
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
);
144 wavefront
.insert(sigmap(c
->getPort(ID(\\A
))));
145 wavefront
.insert(sigmap(c
->getPort(ID(\\B
))));
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
);
155 log(" Finished treeification: Found %d trees.\n", GetSize(tree_list
));
158 bool follow_muxtree(SigBit
&ret_bit
, tree_t
&tree
, SigBit bit
, const char *path
, bool first_layer
= true)
161 if (tree
.muxes
.count(bit
) == 0) {
162 if (first_layer
|| nopartial
)
164 while (path
[0] && path
[1])
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);
180 int prepare_decode_mux(SigBit
&A
, SigBit B
, SigBit sel
, SigBit bit
)
182 if (A
== B
|| sel
== State::Sx
)
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
;
193 auto &entry
= decode_mux_cache
[key
];
194 A
= std::get
<0>(entry
);
195 std::get
<1>(entry
).insert(bit
);
197 if (std::get
<2>(entry
))
200 if (A
== State::Sx
|| B
== State::Sx
)
203 return cost_dmux
/ GetSize(std::get
<1>(entry
));
206 void implement_decode_mux(SigBit ctrl_bit
)
208 if (decode_mux_reverse_cache
.count(ctrl_bit
) == 0)
211 auto &key
= decode_mux_reverse_cache
.at(ctrl_bit
);
212 auto &entry
= decode_mux_cache
[key
];
214 if (std::get
<2>(entry
))
217 implement_decode_mux(std::get
<0>(key
));
218 implement_decode_mux(std::get
<1>(key
));
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
);
225 module
->addMuxGate(NEW_ID
, std::get
<0>(key
), std::get
<1>(key
), std::get
<2>(key
), ctrl_bit
);
226 decode_mux_counter
++;
228 std::get
<2>(entry
) = true;
231 void find_best_covers(tree_t
&tree
, const vector
<SigBit
> &bits
)
233 for (auto bit
: bits
)
234 find_best_cover(tree
, bit
);
237 int sum_best_covers(tree_t
&tree
, const vector
<SigBit
> &bits
)
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
);
248 int find_best_cover(tree_t
&tree
, SigBit bit
)
250 if (tree
.newmuxes
.count(bit
)) {
251 return tree
.newmuxes
.at(bit
).cost
;
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
;
265 ok
= ok
&& follow_muxtree(A
, tree
, bit
, "A");
266 ok
= ok
&& follow_muxtree(B
, tree
, bit
, "B");
268 ok
= ok
&& follow_muxtree(S1
, tree
, bit
, "S");
274 mux
.inputs
.push_back(A
);
275 mux
.inputs
.push_back(B
);
276 mux
.selects
.push_back(S1
);
278 find_best_covers(tree
, mux
.inputs
);
279 log_debug(" Decode cost for mux2 at %s: %d\n", log_signal(bit
), mux
.cost
);
281 mux
.cost
+= cost_mux2
;
282 mux
.cost
+= sum_best_covers(tree
, mux
.inputs
);
284 log_debug(" Cost of mux2 at %s: %d\n", log_signal(bit
), mux
.cost
);
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");
298 ok
= ok
&& follow_muxtree(S1
, tree
, bit
, "AS");
299 ok
= ok
&& follow_muxtree(S2
, tree
, bit
, "BS");
302 ok
= ok
&& xcmp({S1
, S2
});
304 ok
= ok
&& follow_muxtree(T1
, tree
, bit
, "S");
310 mux
.inputs
.push_back(A
);
311 mux
.inputs
.push_back(B
);
312 mux
.inputs
.push_back(C
);
313 mux
.inputs
.push_back(D
);
315 mux
.cost
+= prepare_decode_mux(S1
, S2
, T1
, bit
);
317 mux
.selects
.push_back(S1
);
318 mux
.selects
.push_back(T1
);
320 find_best_covers(tree
, mux
.inputs
);
321 log_debug(" Decode cost for mux4 at %s: %d\n", log_signal(bit
), mux
.cost
);
323 mux
.cost
+= cost_mux4
;
324 mux
.cost
+= sum_best_covers(tree
, mux
.inputs
);
326 log_debug(" Cost of mux4 at %s: %d\n", log_signal(bit
), mux
.cost
);
328 if (best_mux
.cost
>= mux
.cost
)
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");
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");
352 ok
= ok
&& xcmp({S1
, S2
, S3
, S4
});
354 ok
= ok
&& follow_muxtree(T1
, tree
, bit
, "AS");
355 ok
= ok
&& follow_muxtree(T2
, tree
, bit
, "BS");
358 ok
= ok
&& xcmp({T1
, T2
});
360 ok
= ok
&& follow_muxtree(U1
, tree
, bit
, "S");
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
);
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
);
379 mux
.cost
+= prepare_decode_mux(T1
, T2
, U1
, bit
);
381 mux
.selects
.push_back(S1
);
382 mux
.selects
.push_back(T1
);
383 mux
.selects
.push_back(U1
);
385 find_best_covers(tree
, mux
.inputs
);
386 log_debug(" Decode cost for mux8 at %s: %d\n", log_signal(bit
), mux
.cost
);
388 mux
.cost
+= cost_mux8
;
389 mux
.cost
+= sum_best_covers(tree
, mux
.inputs
);
391 log_debug(" Cost of mux8 at %s: %d\n", log_signal(bit
), mux
.cost
);
393 if (best_mux
.cost
>= mux
.cost
)
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");
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");
429 ok
= ok
&& xcmp({S1
, S2
, S3
, S4
, S5
, S6
, S7
, S8
});
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");
437 ok
= ok
&& xcmp({T1
, T2
, T3
, T4
});
439 ok
= ok
&& follow_muxtree(U1
, tree
, bit
, "AS");
440 ok
= ok
&& follow_muxtree(U2
, tree
, bit
, "BS");
443 ok
= ok
&& xcmp({U1
, U2
});
445 ok
= ok
&& follow_muxtree(V1
, tree
, bit
, "S");
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
);
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
);
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
);
480 mux
.cost
+= prepare_decode_mux(U1
, U2
, V1
, bit
);
482 mux
.selects
.push_back(S1
);
483 mux
.selects
.push_back(T1
);
484 mux
.selects
.push_back(U1
);
485 mux
.selects
.push_back(V1
);
487 find_best_covers(tree
, mux
.inputs
);
488 log_debug(" Decode cost for mux16 at %s: %d\n", log_signal(bit
), mux
.cost
);
490 mux
.cost
+= cost_mux16
;
491 mux
.cost
+= sum_best_covers(tree
, mux
.inputs
);
493 log_debug(" Cost of mux16 at %s: %d\n", log_signal(bit
), mux
.cost
);
495 if (best_mux
.cost
>= mux
.cost
)
500 tree
.newmuxes
[bit
] = best_mux
;
501 return best_mux
.cost
;
504 void implement_best_cover(tree_t
&tree
, SigBit bit
, int count_muxes_by_type
[4])
506 newmux_t mux
= tree
.newmuxes
.at(bit
);
508 for (auto inbit
: mux
.inputs
)
509 implement_best_cover(tree
, inbit
, count_muxes_by_type
);
511 for (auto selbit
: mux
.selects
)
512 implement_decode_mux(selbit
);
514 if (GetSize(mux
.inputs
) == 0)
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
);
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
);
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
);
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
);
588 void treecover(tree_t
&tree
)
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
);
602 log("Covering MUX trees in module %s..\n", log_id(module
));
606 log(" Covering trees:\n");
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();
616 for (auto &tree
: tree_list
)
620 log(" Added a total of %d decoder MUXes.\n", decode_mux_counter
);
624 struct MuxcoverPass
: public Pass
{
625 MuxcoverPass() : Pass("muxcover", "cover trees of MUX cells with wider MUXes") { }
626 void help() YS_OVERRIDE
628 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
630 log(" muxcover [options] [selection]\n");
632 log("Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells\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
);
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
);
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
);
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");
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");
659 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
661 log_header(design
, "Executing MUXCOVER pass (mapping to wider MUXes).\n");
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
;
675 for (argidx
= 1; argidx
< args
.size(); argidx
++)
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());
682 if (arg
.size() >= 5 && arg
.compare(0,5,"-mux4") == 0) {
684 if (arg
.size() > 5) {
685 if (arg
[5] != '=') break;
686 cost_mux4
= atoi(arg
.substr(6).c_str());
690 if (arg
.size() >= 5 && arg
.compare(0,5,"-mux8") == 0) {
692 if (arg
.size() > 5) {
693 if (arg
[5] != '=') break;
694 cost_mux8
= atoi(arg
.substr(6).c_str());
698 if (arg
.size() >= 6 && arg
.compare(0,6,"-mux16") == 0) {
700 if (arg
.size() > 6) {
701 if (arg
[6] != '=') break;
702 cost_mux16
= atoi(arg
.substr(7).c_str());
706 if (arg
.size() >= 6 && arg
.compare(0,6,"-dmux=") == 0) {
707 cost_dmux
= atoi(arg
.substr(6).c_str());
710 if (arg
== "-nodecode") {
714 if (arg
== "-nopartial") {
720 extra_args(args
, argidx
, design
);
722 if (!use_mux4
&& !use_mux8
&& !use_mux16
) {
728 for (auto module
: design
->selected_modules())
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
;
746 PRIVATE_NAMESPACE_END