opt_expr: Optimize multiplications with low 0 bits in operands.
authorMarcelina Kościelnicka <mwk@0x04.net>
Sun, 12 Apr 2020 20:37:44 +0000 (22:37 +0200)
committerMarcelina Kościelnicka <mwk@0x04.net>
Mon, 13 Apr 2020 14:52:22 +0000 (16:52 +0200)
Fixes #1500.

passes/opt/opt_expr.cc
tests/opt/opt_expr.ys

index 1a4dd9239a2531aa0d4f26676d5119aea206d1cb..0222df38a51002738491307361fca550e195780c 100644 (file)
@@ -1426,6 +1426,39 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
                                                goto next_cell;
                                        }
                        }
+
+                       sig_a = assign_map(cell->getPort(ID::A));
+                       sig_b = assign_map(cell->getPort(ID::B));
+                       int a_zeros, b_zeros;
+                       for (a_zeros = 0; a_zeros < GetSize(sig_a); a_zeros++)
+                               if (sig_a[a_zeros] != RTLIL::State::S0)
+                                       break;
+                       for (b_zeros = 0; b_zeros < GetSize(sig_b); b_zeros++)
+                               if (sig_b[b_zeros] != RTLIL::State::S0)
+                                       break;
+                       if (a_zeros || b_zeros) {
+                               int y_zeros = a_zeros + b_zeros;
+                               cover("opt.opt_expr.mul_low_zeros");
+
+                               log_debug("Removing low %d A and %d B bits from cell `%s' in module `%s'.\n",
+                                               a_zeros, b_zeros, cell->name.c_str(), module->name.c_str());
+
+                               if (a_zeros) {
+                                       cell->setPort(ID::A, sig_a.extract_end(a_zeros));
+                                       cell->parameters[ID::A_WIDTH] = GetSize(sig_a) - a_zeros;
+                               }
+                               if (b_zeros) {
+                                       cell->setPort(ID::B, sig_b.extract_end(b_zeros));
+                                       cell->parameters[ID::B_WIDTH] = GetSize(sig_b) - b_zeros;
+                               }
+                               cell->setPort(ID::Y, sig_y.extract_end(y_zeros));
+                               cell->parameters[ID::Y_WIDTH] = GetSize(sig_y) - y_zeros;
+                               module->connect(RTLIL::SigSig(sig_y.extract(0, y_zeros), RTLIL::SigSpec(0, y_zeros)));
+                               cell->check();
+
+                               did_something = true;
+                               goto next_cell;
+                       }
                }
 
                if (!keepdc && cell->type.in(ID($div), ID($mod)))
index e0acead82b1114e29697576903cf5f09e199849d..7c446afd1ea2f607eb83133300be68ae2dba240d 100644 (file)
@@ -291,3 +291,31 @@ check
 equiv_opt -assert opt_expr -keepdc
 design -load postopt
 select -assert-count 1 t:$shift r:A_WIDTH=13 %i
+
+###########
+
+design -reset
+read_verilog -icells <<EOT
+module opt_expr_mul_low_bits(input [2:0] a, input [2:0] b, output [7:0] y);
+    \$mul #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(4), .Y_WIDTH(8)) mul (.A({a, 1'b0}), .B({b, 1'b0}), .Y(y));
+endmodule
+EOT
+check
+
+equiv_opt -assert opt_expr
+design -load postopt
+select -assert-count 1 t:$mul r:A_WIDTH=3 %i r:B_WIDTH=3 %i r:Y_WIDTH=6 %i
+
+###########
+
+design -reset
+read_verilog -icells <<EOT
+module opt_expr_mul_low_bits(input [2:0] a, input [2:0] b, output [7:0] y);
+    \$mul #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(4), .Y_WIDTH(8)) mul (.A({a, 1'b0}), .B({b, 1'b0}), .Y(y));
+endmodule
+EOT
+check
+
+equiv_opt -assert opt_expr -keepdc
+design -load postopt
+select -assert-count 1 t:$mul r:A_WIDTH=4 %i r:B_WIDTH=4 %i r:Y_WIDTH=8 %i