Handle $shift and Y_WIDTH > 1 as per @cliffordwolf
authorEddie Hung <eddie@fpgeh.com>
Thu, 22 Aug 2019 15:22:23 +0000 (08:22 -0700)
committerEddie Hung <eddie@fpgeh.com>
Thu, 22 Aug 2019 15:22:23 +0000 (08:22 -0700)
passes/opt/opt_expr.cc
tests/opt/opt_expr.ys

index aca15e5f27243376b4cd21ebe07c067e7c824081..c4da613abd731c0f655298e68241173e610a4cbb 100644 (file)
@@ -745,16 +745,20 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
                        }
                }
 
-               if (cell->type == ID($shiftx) && GetSize(cell->getPort(ID::Y)) == 1) {
+               if (cell->type.in(ID($shiftx), ID($shift))) {
                        SigSpec sig_a = assign_map(cell->getPort(ID::A));
                        int width;
+                       bool trim_x = true;
+                       bool trim_0 = cell->type == ID($shift);
                        for (width = GetSize(sig_a); width > 1; width--) {
-                               if (sig_a[width-1] != State::Sx)
-                                       break;
+                               if ((trim_x && sig_a[width-1] == State::Sx) ||
+                                       (trim_0 && sig_a[width-1] == State::S0))
+                                       continue;
+                               break;
                        }
 
                        if (width < GetSize(sig_a)) {
-                               cover("opt.opt_expr.trim_shiftx");
+                               cover_list("opt.opt_expr.xbit", "$shiftx", "$shift", cell->type.str());
                                sig_a.remove(width, GetSize(sig_a)-width);
                                cell->setPort(ID::A, sig_a);
                                cell->setParam(ID(A_WIDTH), width);
index 4affc1ac851a1e43e1daa4ce41b2211f9139d4d5..02be20a62fde427c08d850844e14ff6b9644128d 100644 (file)
@@ -226,7 +226,7 @@ select -assert-count 1 t:$alu r:A_WIDTH=8 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i
 
 design -reset
 read_verilog -icells <<EOT
-module opt_expr_shiftx(input [2:0] a, input [1:0] b, output y);
+module opt_expr_shiftx_1bit(input [2:0] a, input [1:0] b, output y);
     \$shiftx #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(2), .Y_WIDTH(1)) shiftx (.A({1'bx,a}), .B(b), .Y(y));
 endmodule
 EOT
@@ -235,3 +235,45 @@ check
 equiv_opt opt_expr
 design -load postopt
 select -assert-count 1 t:$shiftx r:A_WIDTH=3 %i
+
+###########
+
+design -reset
+read_verilog -icells <<EOT
+module opt_expr_shiftx_3bit(input [9:0] a, input [3:0] b, output [2:0] y);
+    \$shiftx #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(14), .B_WIDTH(4), .Y_WIDTH(3)) shiftx (.A({4'bxx00,a}), .B(b), .Y(y));
+endmodule
+EOT
+check
+
+equiv_opt opt_expr
+design -load postopt
+select -assert-count 1 t:$shiftx r:A_WIDTH=12 %i
+
+###########
+
+design -reset
+read_verilog -icells <<EOT
+module opt_expr_shift_1bit(input [2:0] a, input [1:0] b, output y);
+    \$shift #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(2), .Y_WIDTH(1)) shift (.A({1'b0,a}), .B(b), .Y(y));
+endmodule
+EOT
+check
+
+equiv_opt opt_expr
+design -load postopt
+select -assert-count 1 t:$shift r:A_WIDTH=3 %i
+
+###########
+
+design -reset
+read_verilog -icells <<EOT
+module opt_expr_shift_3bit(input [9:0] a, input [3:0] b, output [2:0] y);
+    \$shift #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(14), .B_WIDTH(4), .Y_WIDTH(3)) shift (.A({4'b0x0x,a}), .B(b), .Y(y));
+endmodule
+EOT
+check
+
+equiv_opt opt_expr
+design -load postopt
+select -assert-count 1 t:$shift r:A_WIDTH=10 %i