42 for (
auto cell : module->
cells())
43 for (
auto &conn : cell->connections()) {
45 driven_signals.
add(sigmap(conn.second));
47 used_signals.
add(sigmap(conn.second));
50 for (
auto wire : module->
wires()) {
52 driven_signals.
add(sigmap(wire));
53 if (wire->port_output)
54 used_signals.
add(sigmap(wire));
55 all_signals.
add(sigmap(wire));
58 all_signals.
del(driven_signals);
61 for (
auto &c : undriven_signals.
chunks())
65 if (c.wire->name[0] ==
'$')
66 sig = used_signals.
extract(sig);
81 log(
"Replacing %s cell `%s' (%s) in module `%s' with constant driver `%s = %s'.\n",
85 assign_map.
add(Y, out_val);
93 std::string b_name = cell->
hasPort(
"\\B") ?
"\\B" :
"\\A";
95 bool a_signed = cell->
parameters.at(
"\\A_SIGNED").as_bool();
96 bool b_signed = cell->
parameters.at(b_name +
"_SIGNED").as_bool();
103 sig_b.extend_u0(sig_y.size(), b_signed);
105 std::vector<RTLIL::SigBit> bits_a = sig_a, bits_b = sig_b, bits_y = sig_y;
107 enum { GRP_DYN, GRP_CONST_A, GRP_CONST_B, GRP_CONST_AB, GRP_N };
108 std::map<std::pair<RTLIL::SigBit, RTLIL::SigBit>, std::set<RTLIL::SigBit>> grouped_bits[GRP_N];
110 for (
int i = 0; i <
GetSize(bits_y); i++)
112 int group_idx = GRP_DYN;
122 group_idx = GRP_CONST_AB;
124 group_idx = GRP_CONST_A;
125 else if (bit_b.wire ==
NULL && commutative)
126 group_idx = GRP_CONST_A, std::swap(bit_a, bit_b);
127 else if (bit_b.wire ==
NULL)
128 group_idx = GRP_CONST_B;
130 grouped_bits[group_idx][std::pair<RTLIL::SigBit, RTLIL::SigBit>(bit_a, bit_b)].insert(bits_y[i]);
133 for (
int i = 0; i < GRP_N; i++)
137 log(
"Replacing %s cell `%s' in module `%s' with cells using grouped bits:\n",
140 for (
int i = 0; i < GRP_N; i++)
142 if (grouped_bits[i].empty())
149 for (
auto &it : grouped_bits[i]) {
150 for (
auto &bit : it.second) {
164 if (b_name ==
"\\B") {
182 cover_list(
"opt.opt_const.fine.group",
"$not",
"$pos",
"$and",
"$or",
"$xor",
"$xnor", cell->
type.
str());
199 std::map<RTLIL::SigSpec, RTLIL::SigSpec> invert_map;
202 std::map<RTLIL::Cell*, std::set<RTLIL::SigBit>> cell_to_inbit;
203 std::map<RTLIL::SigBit, std::set<RTLIL::Cell*>> outbit_to_cell;
205 for (
auto cell : module->
cells())
206 if (design->
selected(module, cell) && cell->type[0] ==
'$') {
207 if ((cell->type ==
"$_NOT_" || cell->type ==
"$not" || cell->type ==
"$logic_not") &&
208 cell->getPort(
"\\A").size() == 1 && cell->getPort(
"\\Y").size() == 1)
211 for (
auto &conn : cell->connections()) {
214 if (ct_combinational.
cell_input(cell->type, conn.first))
215 cell_to_inbit[cell].insert(sig.
begin(), sig.
end());
216 if (ct_combinational.
cell_output(cell->type, conn.first))
217 for (
auto &bit : sig)
218 outbit_to_cell[bit].insert(cell);
223 for (
auto &it_right : cell_to_inbit)
224 for (
auto &it_sigbit : it_right.second)
225 for (
auto &it_left : outbit_to_cell[it_sigbit])
226 cells.
edge(it_left, it_right.first);
230 for (
auto cell : cells.
sorted)
232 #define ACTION_DO(_p_, _s_) do { cover("opt.opt_const.action_" S__LINE__); replace_cell(assign_map, module, cell, input.as_string(), _p_, _s_); goto next_cell; } while (0)
233 #define ACTION_DO_Y(_v_) ACTION_DO("\\Y", RTLIL::SigSpec(RTLIL::State::S ## _v_))
237 if (cell->type ==
"$not" || cell->type ==
"$pos" ||
238 cell->type ==
"$and" || cell->type ==
"$or" || cell->type ==
"$xor" || cell->type ==
"$xnor")
242 if (cell->type ==
"$reduce_and")
254 }
else if (bit.wire !=
NULL) {
259 cover(
"opt.opt_const.fine.$reduce_and");
260 log(
"Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
262 cell->setPort(
"\\A", sig_a = new_a);
263 cell->parameters.at(
"\\A_WIDTH") = 1;
268 if (cell->type ==
"$logic_not" || cell->type ==
"$logic_and" || cell->type ==
"$logic_or" || cell->type ==
"$reduce_or" || cell->type ==
"$reduce_bool")
280 }
else if (bit.wire !=
NULL) {
285 cover_list(
"opt.opt_const.fine.A",
"$logic_not",
"$logic_and",
"$logic_or",
"$reduce_or",
"$reduce_bool", cell->type.str());
286 log(
"Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
288 cell->setPort(
"\\A", sig_a = new_a);
289 cell->parameters.at(
"\\A_WIDTH") = 1;
294 if (cell->type ==
"$logic_and" || cell->type ==
"$logic_or")
306 }
else if (bit.wire !=
NULL) {
311 cover_list(
"opt.opt_const.fine.B",
"$logic_and",
"$logic_or", cell->type.str());
312 log(
"Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
314 cell->setPort(
"\\B", sig_b = new_b);
315 cell->parameters.at(
"\\B_WIDTH") = 1;
322 cover(
"opt.opt_const.one_high");
328 cover(
"opt.opt_const.one_low");
333 if (cell->type ==
"$reduce_xor" || cell->type ==
"$reduce_xnor" || cell->type ==
"$shift" || cell->type ==
"$shiftx" ||
334 cell->type ==
"$shl" || cell->type ==
"$shr" || cell->type ==
"$sshl" || cell->type ==
"$sshr" ||
335 cell->type ==
"$lt" || cell->type ==
"$le" || cell->type ==
"$ge" || cell->type ==
"$gt" ||
336 cell->type ==
"$neg" || cell->type ==
"$add" || cell->type ==
"$sub" ||
337 cell->type ==
"$mul" || cell->type ==
"$div" || cell->type ==
"$mod" || cell->type ==
"$pow")
342 if (cell->type ==
"$shl" || cell->type ==
"$shr" || cell->type ==
"$sshl" || cell->type ==
"$sshr" || cell->type ==
"$shift" || cell->type ==
"$shiftx")
347 goto found_the_x_bit;
349 for (
auto &bit : sig_b.to_sigbit_vector())
351 goto found_the_x_bit;
355 cover_list(
"opt.opt_const.xbit",
"$reduce_xor",
"$reduce_xnor",
"$shl",
"$shr",
"$sshl",
"$sshr",
"$shift",
"$shiftx",
356 "$lt",
"$le",
"$ge",
"$gt",
"$neg",
"$add",
"$sub",
"$mul",
"$div",
"$mod",
"$pow", cell->type.str());
357 if (cell->type ==
"$reduce_xor" || cell->type ==
"$reduce_xnor" ||
358 cell->type ==
"$lt" || cell->type ==
"$le" || cell->type ==
"$ge" || cell->type ==
"$gt")
366 if ((cell->type ==
"$_NOT_" || cell->type ==
"$not" || cell->type ==
"$logic_not") && cell->getPort(
"\\Y").size() == 1 &&
367 invert_map.count(
assign_map(cell->getPort(
"\\A"))) != 0) {
368 cover_list(
"opt.opt_const.invert.double",
"$_NOT_",
"$not",
"$logic_not", cell->type.str());
369 replace_cell(assign_map, module, cell,
"double_invert",
"\\Y", invert_map.at(assign_map(cell->getPort(
"\\A"))));
373 if ((cell->type ==
"$_MUX_" || cell->type ==
"$mux") && invert_map.count(
assign_map(cell->getPort(
"\\S"))) != 0) {
374 cover_list(
"opt.opt_const.invert.muxsel",
"$_MUX_",
"$mux", cell->type.str());
375 log(
"Optimizing away select inverter for %s cell `%s' in module `%s'.\n",
log_id(cell->type),
log_id(cell),
log_id(module));
377 cell->setPort(
"\\A", cell->getPort(
"\\B"));
378 cell->setPort(
"\\B", tmp);
379 cell->setPort(
"\\S", invert_map.at(assign_map(cell->getPort(
"\\S"))));
384 if (cell->type ==
"$_NOT_") {
386 assign_map.
apply(input);
392 if (cell->type ==
"$_AND_") {
394 input.
append(cell->getPort(
"\\B"));
395 input.
append(cell->getPort(
"\\A"));
396 assign_map.
apply(input);
411 if (cell->type ==
"$_OR_") {
413 input.
append(cell->getPort(
"\\B"));
414 input.
append(cell->getPort(
"\\A"));
415 assign_map.
apply(input);
430 if (cell->type ==
"$_XOR_") {
432 input.
append(cell->getPort(
"\\B"));
433 input.
append(cell->getPort(
"\\A"));
434 assign_map.
apply(input);
445 if (cell->type ==
"$_MUX_") {
447 input.
append(cell->getPort(
"\\S"));
448 input.
append(cell->getPort(
"\\B"));
449 input.
append(cell->getPort(
"\\A"));
450 assign_map.
apply(input);
456 if (input.
match(
"10 ")) {
457 cover(
"opt.opt_const.mux_to_inv");
458 cell->type =
"$_NOT_";
459 cell->setPort(
"\\A", input.
extract(0, 1));
460 cell->unsetPort(
"\\B");
461 cell->unsetPort(
"\\S");
476 if (cell->type ==
"$eq" || cell->type ==
"$ne" || cell->type ==
"$eqx" || cell->type ==
"$nex")
481 if (cell->parameters[
"\\A_WIDTH"].as_int() != cell->parameters[
"\\B_WIDTH"].as_int()) {
482 int width = std::max(cell->parameters[
"\\A_WIDTH"].as_int(), cell->parameters[
"\\B_WIDTH"].as_int());
483 a.
extend_u0(width, cell->parameters[
"\\A_SIGNED"].as_bool() && cell->parameters[
"\\B_SIGNED"].as_bool());
484 b.
extend_u0(width, cell->parameters[
"\\A_SIGNED"].as_bool() && cell->parameters[
"\\B_SIGNED"].as_bool());
490 for (
int i = 0; i <
GetSize(a); i++) {
492 cover_list(
"opt.opt_const.eqneq.isneq",
"$eq",
"$ne",
"$eqx",
"$nex", cell->type.str());
494 new_y.extend(cell->parameters[
"\\Y_WIDTH"].as_int(),
false);
495 replace_cell(assign_map, module, cell,
"isneq",
"\\Y", new_y);
504 if (new_a.
size() == 0) {
505 cover_list(
"opt.opt_const.eqneq.empty",
"$eq",
"$ne",
"$eqx",
"$nex", cell->type.str());
507 new_y.extend(cell->parameters[
"\\Y_WIDTH"].as_int(),
false);
508 replace_cell(assign_map, module, cell,
"empty",
"\\Y", new_y);
513 cover_list(
"opt.opt_const.eqneq.resize",
"$eq",
"$ne",
"$eqx",
"$nex", cell->type.str());
514 cell->setPort(
"\\A", new_a);
515 cell->setPort(
"\\B", new_b);
516 cell->parameters[
"\\A_WIDTH"] = new_a.
size();
517 cell->parameters[
"\\B_WIDTH"] = new_b.
size();
521 if ((cell->type ==
"$eq" || cell->type ==
"$ne") && cell->parameters[
"\\Y_WIDTH"].as_int() == 1 &&
522 cell->parameters[
"\\A_WIDTH"].as_int() == 1 && cell->parameters[
"\\B_WIDTH"].as_int() == 1)
528 cover_list(
"opt.opt_const.eqneq.swapconst",
"$eq",
"$ne", cell->type.str());
530 cell->setPort(
"\\A", cell->getPort(
"\\B"));
531 cell->setPort(
"\\B", tmp);
534 if (b.is_fully_const()) {
535 if (b.as_bool() == (cell->type ==
"$eq")) {
539 cover_list(
"opt.opt_const.eqneq.isnot",
"$eq",
"$ne", cell->type.str());
540 log(
"Replacing %s cell `%s' in module `%s' with inverter.\n",
log_id(cell->type),
log_id(cell),
log_id(module));
542 cell->parameters.erase(
"\\B_WIDTH");
543 cell->parameters.erase(
"\\B_SIGNED");
544 cell->unsetPort(
"\\B");
551 if (cell->type.in(
"$shl",
"$shr",
"$sshl",
"$sshr",
"$shift",
"$shiftx") &&
assign_map(cell->getPort(
"\\B")).is_fully_const())
553 bool sign_ext = cell->type ==
"$sshr" && cell->getParam(
"\\A_SIGNED").as_bool();
554 int shift_bits =
assign_map(cell->getPort(
"\\B")).as_int(cell->type.in(
"$shift",
"$shiftx") && cell->getParam(
"\\B_SIGNED").as_bool());
556 if (cell->type.in(
"$shl",
"$sshl"))
563 sig_a.
extend(
GetSize(sig_y), cell->getParam(
"\\A_SIGNED").as_bool());
565 for (
int i = 0; i <
GetSize(sig_y); i++) {
566 int idx = i + shift_bits;
567 if (0 <= idx && idx <
GetSize(sig_a))
568 sig_y[i] = sig_a[idx];
569 else if (
GetSize(sig_a) <= idx && sign_ext)
570 sig_y[i] = sig_a[
GetSize(sig_a)-1];
573 cover_list(
"opt.opt_const.constshift",
"$shl",
"$shr",
"$sshl",
"$sshr",
"$shift",
"$shiftx", cell->type.str());
575 log(
"Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n",
578 module->
connect(cell->getPort(
"\\Y"), sig_y);
587 bool identity_wrt_a =
false;
588 bool identity_wrt_b =
false;
590 if (cell->type ==
"$add" || cell->type ==
"$sub" || cell->type ==
"$or" || cell->type ==
"$xor")
596 identity_wrt_b =
true;
598 if (b.is_fully_const() && b.as_bool() ==
false)
599 identity_wrt_a =
true;
602 if (cell->type ==
"$shl" || cell->type ==
"$shr" || cell->type ==
"$sshl" || cell->type ==
"$sshr" || cell->type ==
"$shift" || cell->type ==
"$shiftx")
607 identity_wrt_a =
true;
610 if (cell->type ==
"$mul")
616 identity_wrt_b =
true;
618 if (b.is_fully_const() && b.size() <= 32 && b.as_int() == 1)
619 identity_wrt_a =
true;
622 if (cell->type ==
"$div")
627 identity_wrt_a =
true;
630 if (identity_wrt_a || identity_wrt_b)
633 cover_list(
"opt.opt_const.identwrt.a",
"$add",
"$sub",
"$or",
"$xor",
"$shl",
"$shr",
"$sshl",
"$sshr",
"$shift",
"$shiftx",
"$mul",
"$div", cell->type.str());
635 cover_list(
"opt.opt_const.identwrt.b",
"$add",
"$sub",
"$or",
"$xor",
"$shl",
"$shr",
"$sshl",
"$sshr",
"$shift",
"$shiftx",
"$mul",
"$div", cell->type.str());
637 log(
"Replacing %s cell `%s' in module `%s' with identity for port %c.\n",
638 cell->type.c_str(), cell->name.c_str(), module->
name.
c_str(), identity_wrt_a ?
'A' :
'B');
640 if (!identity_wrt_a) {
641 cell->setPort(
"\\A", cell->getPort(
"\\B"));
642 cell->parameters.at(
"\\A_WIDTH") = cell->parameters.at(
"\\B_WIDTH");
643 cell->parameters.at(
"\\A_SIGNED") = cell->parameters.at(
"\\B_SIGNED");
647 cell->unsetPort(
"\\B");
648 cell->parameters.erase(
"\\B_WIDTH");
649 cell->parameters.erase(
"\\B_SIGNED");
657 if (mux_bool && (cell->type ==
"$mux" || cell->type ==
"$_MUX_") &&
659 cover_list(
"opt.opt_const.mux_bool",
"$mux",
"$_MUX_", cell->type.str());
660 replace_cell(assign_map, module, cell,
"mux_bool",
"\\Y", cell->getPort(
"\\S"));
664 if (mux_bool && (cell->type ==
"$mux" || cell->type ==
"$_MUX_") &&
666 cover_list(
"opt.opt_const.mux_invert",
"$mux",
"$_MUX_", cell->type.str());
667 log(
"Replacing %s cell `%s' in module `%s' with inverter.\n",
log_id(cell->type),
log_id(cell),
log_id(module));
668 cell->setPort(
"\\A", cell->getPort(
"\\S"));
669 cell->unsetPort(
"\\B");
670 cell->unsetPort(
"\\S");
671 if (cell->type ==
"$mux") {
672 cell->parameters[
"\\A_WIDTH"] = cell->parameters[
"\\WIDTH"];
673 cell->parameters[
"\\Y_WIDTH"] = cell->parameters[
"\\WIDTH"];
674 cell->parameters[
"\\A_SIGNED"] = 0;
675 cell->parameters.erase(
"\\WIDTH");
678 cell->type =
"$_NOT_";
683 if (consume_x && mux_bool && (cell->type ==
"$mux" || cell->type ==
"$_MUX_") && cell->getPort(
"\\A") ==
RTLIL::SigSpec(0, 1)) {
684 cover_list(
"opt.opt_const.mux_and",
"$mux",
"$_MUX_", cell->type.str());
685 log(
"Replacing %s cell `%s' in module `%s' with and-gate.\n",
log_id(cell->type),
log_id(cell),
log_id(module));
686 cell->setPort(
"\\A", cell->getPort(
"\\S"));
687 cell->unsetPort(
"\\S");
688 if (cell->type ==
"$mux") {
689 cell->parameters[
"\\A_WIDTH"] = cell->parameters[
"\\WIDTH"];
690 cell->parameters[
"\\B_WIDTH"] = cell->parameters[
"\\WIDTH"];
691 cell->parameters[
"\\Y_WIDTH"] = cell->parameters[
"\\WIDTH"];
692 cell->parameters[
"\\A_SIGNED"] = 0;
693 cell->parameters[
"\\B_SIGNED"] = 0;
694 cell->parameters.erase(
"\\WIDTH");
697 cell->type =
"$_AND_";
702 if (consume_x && mux_bool && (cell->type ==
"$mux" || cell->type ==
"$_MUX_") && cell->getPort(
"\\B") ==
RTLIL::SigSpec(1, 1)) {
703 cover_list(
"opt.opt_const.mux_or",
"$mux",
"$_MUX_", cell->type.str());
704 log(
"Replacing %s cell `%s' in module `%s' with or-gate.\n",
log_id(cell->type),
log_id(cell),
log_id(module));
705 cell->setPort(
"\\B", cell->getPort(
"\\S"));
706 cell->unsetPort(
"\\S");
707 if (cell->type ==
"$mux") {
708 cell->parameters[
"\\A_WIDTH"] = cell->parameters[
"\\WIDTH"];
709 cell->parameters[
"\\B_WIDTH"] = cell->parameters[
"\\WIDTH"];
710 cell->parameters[
"\\Y_WIDTH"] = cell->parameters[
"\\WIDTH"];
711 cell->parameters[
"\\A_SIGNED"] = 0;
712 cell->parameters[
"\\B_SIGNED"] = 0;
713 cell->parameters.erase(
"\\WIDTH");
716 cell->type =
"$_OR_";
721 if (mux_undef && (cell->type ==
"$mux" || cell->type ==
"$pmux")) {
723 int width = cell->getPort(
"\\A").
size();
724 if ((cell->getPort(
"\\A").is_fully_undef() && cell->getPort(
"\\B").is_fully_undef()) ||
725 cell->getPort(
"\\S").is_fully_undef()) {
726 cover_list(
"opt.opt_const.mux_undef",
"$mux",
"$pmux", cell->type.str());
727 replace_cell(assign_map, module, cell,
"mux_undef",
"\\Y", cell->getPort(
"\\A"));
730 for (
int i = 0; i < cell->getPort(
"\\S").size(); i++) {
738 new_a = cell->getPort(
"\\A");
740 new_a = new_b.
extract((new_s.
size()-1)*width, width);
744 if (new_s.
size() == 0) {
745 cover_list(
"opt.opt_const.mux_empty",
"$mux",
"$pmux", cell->type.str());
746 replace_cell(assign_map, module, cell,
"mux_empty",
"\\Y", new_a);
750 cover_list(
"opt.opt_const.mux_sel01",
"$mux",
"$pmux", cell->type.str());
751 replace_cell(assign_map, module, cell,
"mux_sel01",
"\\Y", new_s);
754 if (cell->getPort(
"\\S").size() != new_s.
size()) {
755 cover_list(
"opt.opt_const.mux_reduce",
"$mux",
"$pmux", cell->type.str());
756 log(
"Optimized away %d select inputs of %s cell `%s' in module `%s'.\n",
758 cell->setPort(
"\\A", new_a);
759 cell->setPort(
"\\B", new_b);
760 cell->setPort(
"\\S", new_s);
761 if (new_s.
size() > 1) {
762 cell->type =
"$pmux";
763 cell->parameters[
"\\S_WIDTH"] = new_s.
size();
766 cell->parameters.erase(
"\\S_WIDTH");
772 #define FOLD_1ARG_CELL(_t) \
773 if (cell->type == "$" #_t) { \
774 RTLIL::SigSpec a = cell->getPort("\\A"); \
775 assign_map.apply(a); \
776 if (a.is_fully_const()) { \
777 RTLIL::Const dummy_arg(RTLIL::State::S0, 1); \
778 RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), dummy_arg, \
779 cell->parameters["\\A_SIGNED"].as_bool(), false, \
780 cell->parameters["\\Y_WIDTH"].as_int())); \
781 cover("opt.opt_const.const.$" #_t); \
782 replace_cell(assign_map, module, cell, stringf("%s", log_signal(a)), "\\Y", y); \
786 #define FOLD_2ARG_CELL(_t) \
787 if (cell->type == "$" #_t) { \
788 RTLIL::SigSpec a = cell->getPort("\\A"); \
789 RTLIL::SigSpec b = cell->getPort("\\B"); \
790 assign_map.apply(a), assign_map.apply(b); \
791 if (a.is_fully_const() && b.is_fully_const()) { \
792 RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), b.as_const(), \
793 cell->parameters["\\A_SIGNED"].as_bool(), \
794 cell->parameters["\\B_SIGNED"].as_bool(), \
795 cell->parameters["\\Y_WIDTH"].as_int())); \
796 cover("opt.opt_const.const.$" #_t); \
797 replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), "\\Y", y); \
843 if (cell->type ==
"$mux") {
848 ACTION_DO(
"\\Y", input.
as_bool() ? cell->getPort(
"\\B") : cell->getPort(
"\\A"));
853 if (!keepdc && cell->type ==
"$mul")
855 bool a_signed = cell->parameters[
"\\A_SIGNED"].as_bool();
856 bool b_signed = cell->parameters[
"\\B_SIGNED"].as_bool();
857 bool swapped_ab =
false;
863 if (sig_b.is_fully_const() && sig_b.size() <= 32)
864 std::swap(sig_a, sig_b), std::swap(a_signed, b_signed), swapped_ab =
true;
868 int a_val = sig_a.
as_int();
872 cover(
"opt.opt_const.mul_shift.zero");
874 log(
"Replacing multiply-by-zero cell `%s' in module `%s' with zero-driver.\n",
875 cell->name.c_str(), module->
name.
c_str());
884 for (
int i = 1; i < (a_signed ? sig_a.
size()-1 : sig_a.
size()); i++)
885 if (a_val == (1 << i))
888 cover(
"opt.opt_const.mul_shift.swapped");
890 cover(
"opt.opt_const.mul_shift.unswapped");
892 log(
"Replacing multiply-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
893 a_val, cell->name.c_str(), module->
name.
c_str(), i);
896 cell->setPort(
"\\A", cell->getPort(
"\\B"));
897 cell->parameters[
"\\A_WIDTH"] = cell->parameters[
"\\B_WIDTH"];
898 cell->parameters[
"\\A_SIGNED"] = cell->parameters[
"\\B_SIGNED"];
907 cell->parameters[
"\\B_WIDTH"] =
GetSize(new_b);
908 cell->parameters[
"\\B_SIGNED"] =
false;
909 cell->setPort(
"\\B", new_b);
921 #undef FOLD_1ARG_CELL
922 #undef FOLD_2ARG_CELL
932 log(
" opt_const [options] [selection]\n");
934 log(
"This pass performs const folding on internal cell types with constant inputs.\n");
936 log(
" -mux_undef\n");
937 log(
" remove 'undef' inputs from $mux, $pmux and $_MUX_ cells\n");
940 log(
" replace $mux cells with inverters or buffers when possible\n");
943 log(
" replace undriven nets with undef (x) constants\n");
946 log(
" perform fine-grain optimizations\n");
949 log(
" alias for -mux_undef -mux_bool -undriven -fine\n");
952 log(
" some optimizations change the behavior of the circuit with respect to\n");
953 log(
" don't-care bits. for example in 'a+0' a single x-bit in 'a' will cause\n");
954 log(
" all result bits to be set to x. this behavior changes when 'a+0' is\n");
955 log(
" replaced by 'a'. the -keepdc option disables all such optimizations.\n");
960 bool mux_undef =
false;
961 bool mux_bool =
false;
962 bool undriven =
false;
963 bool do_fine =
false;
966 log_header(
"Executing OPT_CONST pass (perform const folding).\n");
970 for (argidx = 1; argidx < args.size(); argidx++) {
971 if (args[argidx] ==
"-mux_undef") {
975 if (args[argidx] ==
"-mux_bool") {
979 if (args[argidx] ==
"-undriven") {
983 if (args[argidx] ==
"-fine") {
987 if (args[argidx] ==
"-full") {
994 if (args[argidx] ==
"-keepdc") {
const char * c_str() const
bool selected(T1 *module) const
bool is_fully_def() const
RTLIL::SigSpec extract(RTLIL::SigSpec sig)
bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutative, SigMap &sigmap)
#define ACTION_DO(_p_, _s_)
bool is_fully_undef() const
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
void log_header(const char *format,...)
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
static std::string idx(std::string str)
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
RTLIL::ObjRange< RTLIL::Wire * > wires()
std::map< RTLIL::IdString, RTLIL::Const > parameters
OptConstPass OptConstPass
void extend_u0(int width, bool is_signed=false)
#define FOLD_2ARG_CELL(_t)
void apply(RTLIL::SigBit &bit) const
bool match(std::string pattern) const
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN bool did_something
bool cell_known(RTLIL::IdString type)
void connect(const RTLIL::SigSig &conn)
void append_bit(const RTLIL::SigBit &bit)
#define PRIVATE_NAMESPACE_BEGIN
RTLIL_ATTRIBUTE_MEMBERS bool hasPort(RTLIL::IdString portname) const
bool cell_output(RTLIL::IdString type, RTLIL::IdString port)
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
void edge(T left, T right)
int GetSize(RTLIL::Wire *wire)
RTLIL::SigSpecIterator begin()
#define log_assert(_assert_expr_)
bool is_fully_const() const
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
RTLIL::SigSpec export_all()
#define PRIVATE_NAMESPACE_END
static const char * id2cstr(const RTLIL::IdString &str)
void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool consume_x, bool mux_undef, bool mux_bool, bool do_fine, bool keepdc)
void add(RTLIL::SigSpec sig)
#define USING_YOSYS_NAMESPACE
RTLIL::ObjRange< RTLIL::Cell * > cells()
RTLIL::ObjRange< RTLIL::Module * > modules()
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)
int as_int(bool is_signed=false) const
void remove(const std::set< RTLIL::Wire * > &wires)
void log(const char *format,...)
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other=NULL) const
void scratchpad_set_bool(std::string varname, bool value)
static RTLIL::State logic_or(RTLIL::State a, RTLIL::State b)
void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
void append(const RTLIL::SigSpec &signal)
void extend(int width, bool is_signed=false)
void add(RTLIL::SigSpec from, RTLIL::SigSpec to)
bool cell_input(RTLIL::IdString type, RTLIL::IdString port)
void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, std::string info, std::string out_port, RTLIL::SigSpec out_val)
void del(RTLIL::SigSpec sig)
static RTLIL::State logic_and(RTLIL::State a, RTLIL::State b)
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
std::pair< SigSpec, SigSpec > SigSig
const char * log_id(RTLIL::IdString str)
RTLIL::SigSpecIterator end()
std::vector< RTLIL::SigBit > to_sigbit_vector() const
#define FOLD_1ARG_CELL(_t)
const std::vector< RTLIL::SigChunk > & chunks() const