3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-23 17:15:33 +00:00

muxadd and muldiv_c peepopt

This commit is contained in:
Alain Dargelas 2025-01-15 16:57:19 -08:00
parent 8dabfbe429
commit 31a5197a1c
9 changed files with 902 additions and 38 deletions

1
tests/peepopt/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/*.log

343
tests/peepopt/muldiv_c.ys Normal file
View file

@ -0,0 +1,343 @@
log -header "Test simple positive case"
log -push
design -reset
read_verilog <<EOF
module top (
input wire [11:0] a,
output wire [11:0] y
);
assign y = (a * 16'd5140) / (257 * 2);
endmodule
EOF
check -assert
equiv_opt -assert peepopt
design -load postopt
select -assert-none t:$div
design -reset
log -pop
log -header "Test negative case where div is kept"
log -push
design -reset
read_verilog <<EOF
module top (
input wire signed [11:0] a,
output wire signed [31:0] y,
output wire probe
);
wire [28:0] tmp = (a * 16'd5140);
assign probe = tmp[28];
assign y = tmp[27:0] / (257 * 2);
endmodule
EOF
check -assert
equiv_opt -assert peepopt
design -load postopt
select -assert-any t:$div
design -reset
log -pop
log -header "Basic pattern transformed: (a * b) / c"
log -push
read_verilog <<EOT
module top(
input signed [3:0] a,
output signed [7:0] y,
);
wire signed [7:0] mul;
assign mul = a * 4'sd6;
assign y = mul / 8'sd3;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 0 t:$div
design -reset
log -pop
log -header "Transformed on symmetry in multiplication"
log -push
read_verilog <<EOT
module top(
input signed [3:0] a,
output signed [7:0] y,
);
wire signed [7:0] mul;
assign mul = 4'sd6 * a;
assign y = mul / 8'sd3;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 0 t:$div
design -reset
log -pop
log -header "Transformed on b == c"
log -push
read_verilog <<EOT
module top(
input signed [3:0] a,
output signed [7:0] y,
);
wire signed [7:0] mul;
assign mul = a * 4'sd6;
assign y = mul / 8'sd6;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 0 t:$div
design -reset
log -pop
log -header "b negative, c positive"
log -push
read_verilog <<EOT
module top(
input signed [3:0] a,
output signed [7:0] y,
);
wire signed [7:0] mul;
assign mul = a * -4'sd6;
assign y = mul / 8'sd3;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 0 t:$div
design -reset
log -pop
log -header "b positive, c negative"
log -push
read_verilog <<EOT
module top(
input signed [3:0] a,
output signed [7:0] y,
);
wire signed [7:0] mul;
assign mul = a * 4'sd6;
assign y = mul / -8'sd3;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 0 t:$div
design -reset
log -pop
log -header "No transform when b not divisible by c"
log -push
read_verilog <<EOT
module top(
input signed [3:0] a,
output signed [7:0] y,
);
wire signed [7:0] mul;
assign mul = a * 4'sd3;
assign y = mul / 8'sd2;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 1 t:$div
design -reset
log -pop
log -header "No transform when product has a second fanout"
log -push
read_verilog <<EOT
module top(
input signed [3:0] a,
output signed [7:0] y,
output signed [7:0] z,
);
wire signed [7:0] mul;
assign mul = a * 4'sd6;
assign y = mul / 8'sd3;
assign z = mul;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 1 t:$div
design -reset
log -pop
log -header "No transform when divisor is 0"
log -push
read_verilog <<EOT
module top(
input signed [3:0] a,
output signed [7:0] y,
);
wire signed [7:0] mul;
assign mul = a * 4'sd4;
assign y = mul / 8'sd0;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 1 t:$div
design -reset
log -pop
log -header "No transform when (a*b) output can overflow (dividers A input signed)"
log -push
read_verilog <<EOT
module top(
input signed [3:0] a,
output signed [7:0] y,
);
wire signed [5:0] mul;
assign mul = a * 4'sd6;
assign y = mul / 8'sd3;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 1 t:$div
design -reset
log -pop
log -header "No transform when (a*b) output can overflow (dividers A input signed)"
log -push
read_verilog <<EOT
module top(
input signed [3:0] a,
output signed [7:0] y,
);
wire signed [6:0] mul;
assign mul = a * 4'sd6;
assign y = mul / 8'sd3;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 1 t:$div
design -reset
log -pop
log -header "No transform when (a*b) output can overflow (dividers A input unsigned)"
log -push
read_verilog <<EOT
module top(
input [3:0] a,
output [7:0] y,
);
wire [4:0] mul;
assign mul = a * 4'd4;
assign y = mul / 8'd2;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 1 t:$div
design -reset
log -pop
log -header "No transform when (a*b) output can overflow (dividers A input unsigned)"
log -push
read_verilog <<EOT
module top(
input [3:0] a,
output [7:0] y,
);
wire [6:0] mul;
assign mul = a * 4'd8;
assign y = mul / 8'd2;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 1 t:$div
design -reset
log -pop
log -header "No transform when (a*b) and x/c fitting criteria but not connected (x != a*b)"
log -push
read_verilog <<EOT
module top(
input signed [3:0] a,
input signed [7:0] b,
output signed [7:0] y,
output signed [7:0] z,
);
assign y = a * 4'sd6;
assign z = b / 8'sd3;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 1 t:$div
design -reset
log -pop
log -header "No transform when b only divisible by c if b misinterpreted as unsigned"
# b 1001 is -7 but 9 misinterpreted
# c 11 is 3
log -push
read_verilog <<EOT
module top(
input signed [3:0] a,
output signed [7:0] y,
);
wire signed [7:0] mul;
assign mul = a * 4'sb1001;
assign y = mul / 8'sb11;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 1 t:$div
design -reset
log -pop
log -header "Transform even if (a*b) result would overflow if dividers A input signedness is confused & (A input is unsigned)"
log -push
# Transform even if:
# (a*b) result would overflow if dividers A input signedness is confused
# (A input is unsigned)
read_verilog <<EOT
module top(
input [3:0] a,
output [7:0] y,
);
wire [7:0] mul;
assign mul = a * 4'd6;
assign y = mul / 8'd3;
endmodule
EOT
equiv_opt -assert peepopt
design -load postopt
select -assert-count 1 t:$mul
select -assert-count 0 t:$div
design -reset

378
tests/peepopt/muxadd.ys Normal file
View file

@ -0,0 +1,378 @@
log -header "Test basic s?(a+b):a pattern gets transformed (a,b module inputs)"
log -push
design -reset
log -header "Test basic s?(a+b):a pattern gets transformed (a,b module inputs)"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [3:0] a;
input wire [3:0] b;
input wire s;
output wire [3:0] y;
wire [3:0] ab = a + b;
assign y = s ? ab : a;
endmodule
EOF
check -assert
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-any t:$add %co1 %a w:y %i # assert adder rewired
log -pop
log -header "Test basic s?(a+b):a pattern gets transformed (a,b module inputs)"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [3:0] a;
input wire [3:0] b;
input wire s;
output wire [3:0] y;
assign y = s ? (a + b) : a;
endmodule
EOF
check -assert
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-any t:$add %co1 %a w:y %i # assert adder rewired
log -pop
log -header "Test basic s?(a+b):a pattern with intermediate var gets transformed (a,b module inputs)"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [3:0] a;
input wire [3:0] b;
input wire s;
output wire [3:0] y;
wire [3:0] ab = a + b;
assign y = s ? ab : a;
endmodule
EOF
check -assert
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-any t:$add %co1 %a w:y %i # assert adder rewired
log -pop
log -header "Test basic s?(a+b):a pattern gets transformed (a is driven by a cell)"
log -push
design -reset
read_verilog <<EOF
module top(a_, b, s, y);
input wire [3:0] a_;
wire [3:0] a = ~a_;
input wire [3:0] b;
input wire s;
output wire [3:0] y;
wire [3:0] ab = a + b;
assign y = s ? ab : a;
endmodule
EOF
check -assert
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-any t:$add %co1 %a w:y %i # assert adder rewired
log -pop
log -header "Test basic s?(a+b):a pattern gets transformed (b is driven by a cell, output consumed by a cell)"
log -push
design -reset
read_verilog <<EOF
module top(a, b_, f, s, y_);
input wire [3:0] a;
input wire [3:0] b_;
input wire [3:0] f;
wire [3:0] b = b_ ^ f;
input wire s;
wire [3:0] y;
output wire [3:0] y_;
assign y_ = ~y;
wire [3:0] ab = a + b;
assign y = s ? ab : a;
endmodule
EOF
check -assert
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-any t:$add %co1 %a w:y %i # assert adder rewired
log -pop
log -header "Test no transform when a+b has more fanouts (module output)"
log -push
design -reset
read_verilog <<EOF
module top(a, b, ab, s, y);
input wire [2:0] a;
input wire [2:0] b;
output wire [2:0] ab;
output wire [2:0] y;
input wire s;
assign ab = a + b;
assign y = s ? ab : a;
endmodule
EOF
check -assert
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-none t:$add %co1 %a w:y %i
log -pop
log -header "Test no transform when a+b has more fanouts (single bit, cell)"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y, z);
input wire [2:0] a;
input wire [2:0] b;
output wire [2:0] y;
input wire s;
wire [2:0] ab = a + b;
assign y = s ? ab : a;
output wire [2:0] z = !ab[1];
endmodule
EOF
check -assert
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-none t:$add %co1 %a w:y %i
log -pop
log -header "Test no transform when a+b width smaller than a's width"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [3:0] a;
input wire [3:0] b;
output wire [3:0] y;
input wire s;
wire [2:0] ab = a + b;
assign y = s ? ab : a;
endmodule
EOF
check -assert
wreduce
opt_clean
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-none t:$add %co1 %a w:y %i
log -pop
log -header "Test no transform when (a+b) wider than a, adders a input is unsigned, a is not padded with zeros on the muxes input"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [2:0] a;
input wire [3:0] b;
output wire [3:0] y;
input wire s;
wire [3:0] ab = a + b;
assign y = s ? ab : {a[2], a};
endmodule
EOF
check -assert
wreduce
opt_clean
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-none t:$add %co1 %a w:y %i
log -pop
log -header "Test no transform when (a+b) wider than a, adders a input is signed, a is not sign-extended on the muxes input"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [2:0] a;
input wire [3:0] b;
output wire [3:0] y;
input wire s;
wire signed [3:0] ab = $signed(a) + $signed(b);
assign y = s ? ab : {1'b0, a};
endmodule
EOF
check -assert
wreduce
opt_clean
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-none t:$add %co1 %a w:y %i
log -pop
log -header "Test no transform when adder and mux not connected together but otherwise fitting transform. criteria"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [3:0] a;
input wire [3:0] b;
output wire [3:0] y;
input wire s;
wire [3:0] ab = a + b;
wire [3:0] ab_ = !a;
assign y = s ? ab_ : a;
endmodule
EOF
check -assert
wreduce
opt_clean
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-none t:$add %co1 %a w:y %i
log -pop
log -header "Test transform when (a+b) wider than a, adders a input is unsigned, a padded with zeros on the muxes input"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [2:0] a;
input wire [3:0] b;
output wire [3:0] y;
input wire s;
wire [3:0] ab = a + b;
assign y = s ? ab : {1'b0, a};
endmodule
EOF
check -assert
wreduce
opt_clean
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-any t:$add %co1 %a w:y %i
log -pop
log -header "Test transform when (a+b) wider than a, adders a input is signed, a sign-extended on the muxes input"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [2:0] a;
input wire [3:0] b;
output wire [3:0] y;
input wire s;
wire signed [3:0] ab = $signed(a) + $signed(b);
assign y = s ? ab : {a[2], a};
endmodule
EOF
check -assert
wreduce
opt_clean
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-any t:$add %co1 %a w:y %i
log -pop
log -header "Test transform when pattern is s?a:(a+b)"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [3:0] a;
input wire [3:0] b;
output wire [3:0] y;
input wire s;
wire signed [3:0] ab = a + b;
assign y = s ? a : ab;
endmodule
EOF
check -assert
wreduce
opt_clean
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-any t:$add %co1 %a w:y %i # assert adder rewired
log -pop
log -header "Test transform when pattern is a?(b+a):a"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [3:0] a;
input wire [3:0] b;
output wire [3:0] y;
input wire s;
wire signed [3:0] ab = b + a;
assign y = s ? ab : a;
endmodule
EOF
check -assert
wreduce
opt_clean
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-any t:$add %co1 %a w:y %i # assert adder rewired
log -pop
log -header "Test transform when widths b > (a+b) > a"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [2:0] a;
input wire [4:0] b;
output wire [3:0] y;
input wire s;
wire signed [3:0] ab = a + b;
assign y = s ? ab : a;
endmodule
EOF
check -assert
wreduce
opt_clean
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-any t:$add %co1 %a w:y %i # assert adder rewired
log -pop
log -header "Test transform when widths (a+b) > a > b"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [2:0] a;
input wire [3:0] b;
output wire [4:0] y;
input wire s;
wire signed [4:0] ab = a + b;
assign y = s ? ab : a;
endmodule
EOF
check -assert
wreduce
opt_clean
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-any t:$add %co1 %a w:y %i # assert adder rewired
log -pop
log -header "Test transform when widths (a+b) > b > a"
log -push
design -reset
read_verilog <<EOF
module top(a, b, s, y);
input wire [3:0] a;
input wire [2:0] b;
output wire [4:0] y;
input wire s;
wire signed [4:0] ab = a + b;
assign y = s ? ab : a;
endmodule
EOF
check -assert
wreduce
opt_clean
equiv_opt -assert peepopt -withmuxadd
design -load postopt
select -assert-any t:$add %co1 %a w:y %i # assert adder rewired

6
tests/peepopt/run-test.sh Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -e
for x in *.ys; do
echo "Running $x.."
../../yosys -ql ${x%.ys}.log $x
done