This commit is contained in:
nella 2026-06-10 09:38:12 +00:00 committed by GitHub
commit 9557a885b2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 169 additions and 0 deletions

View File

@ -1970,6 +1970,56 @@ skip_identity:
}
skip_alu_split:
// replace (2^k-1)-x with ~x when x is known to be smaller than 2^k
if (do_fine && cell->type == ID($sub))
{
int y_width = GetSize(cell->getPort(ID::Y));
bool a_signed = cell->getParam(ID::A_SIGNED).as_bool();
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
sig_a.extend_u0(y_width, a_signed);
if (y_width > 0 && sig_a.is_fully_const())
{
RTLIL::Const a_val = sig_a.as_const();
int k = 0;
while (k < y_width && a_val[k] == State::S1)
k++;
bool a_is_mask = k > 0;
for (int i = k; a_is_mask && i < y_width; i++)
if (a_val[i] != State::S0)
a_is_mask = false;
if (a_is_mask)
{
bool b_signed = cell->getParam(ID::B_SIGNED).as_bool();
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
sig_b.extend_u0(y_width, b_signed);
bool b_fits = true;
for (int i = k; b_fits && i < y_width; i++)
if (sig_b[i] != State::S0)
b_fits = false;
if (b_fits)
{
RTLIL::SigSpec sig_y = module->Not(NEW_ID, sig_b.extract(0, k));
if (y_width > k)
sig_y.append(RTLIL::SigSpec(State::S0, y_width - k));
log_debug("Replacing `(2^%d-1) - B` $sub cell `%s' in module `%s' with $not.\n",
k, cell->name.c_str(), module->name.c_str());
module->connect(cell->getPort(ID::Y), sig_y);
module->remove(cell);
did_something = true;
goto next_cell;
}
}
}
}
// remove redundant pairs of bits in ==, ===, !=, and !==
// replace cell with const driver if inputs can't be equal
if (do_fine && cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex)))

View File

@ -0,0 +1,19 @@
# https://github.com/YosysHQ/yosys/issues/892
read_verilog <<EOT
module top (input clk, sel, di, output do);
reg [0:1] data [0:0];
always @(posedge clk)
data[0] <= {di, data[0][0]};
assign do = data[0][sel];
endmodule
EOT
proc
equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad
design -load postopt
select -assert-count 1 t:BUFG
select -assert-count 2 t:FDRE
select -assert-count 1 t:LUT3
select -assert-none t:BUFG t:FDRE t:LUT3 %% t:* %D

View File

@ -0,0 +1,100 @@
# Rewrite (2^k-1)-x into ~x when x is known to be smaller than 2^k
read_verilog -icells <<EOT
module test(input [3:0] b, output [3:0] y);
$sub #(
.A_WIDTH(4), .B_WIDTH(4), .Y_WIDTH(4),
.A_SIGNED(0), .B_SIGNED(0),
) sub (
.A(4'hf), .B(b), .Y(y),
);
endmodule
EOT
equiv_opt -assert opt_expr -fine
design -load postopt
select -assert-count 1 t:$not
select -assert-none t:$sub
select -assert-none t:$not t:* %D
design -reset
read_verilog -icells <<EOT
module test(input [1:0] b, output [3:0] y);
$sub #(
.A_WIDTH(4), .B_WIDTH(2), .Y_WIDTH(4),
.A_SIGNED(0), .B_SIGNED(0),
) sub (
.A(4'd3), .B(b), .Y(y),
);
endmodule
EOT
equiv_opt -assert opt_expr -fine
design -load postopt
select -assert-count 1 t:$not
select -assert-none t:$sub
design -reset
read_verilog -icells <<EOT
module test(input [3:0] b, output [3:0] y);
$sub #(
.A_WIDTH(4), .B_WIDTH(4), .Y_WIDTH(4),
.A_SIGNED(0), .B_SIGNED(0),
) sub (
.A(4'b1011), .B(b), .Y(y),
);
endmodule
EOT
equiv_opt -assert opt_expr -fine
design -load postopt
select -assert-none t:$not
design -reset
read_verilog -icells <<EOT
module test(input [3:0] b, output [3:0] y);
$sub #(
.A_WIDTH(2), .B_WIDTH(4), .Y_WIDTH(4),
.A_SIGNED(0), .B_SIGNED(0),
) sub (
.A(2'b11), .B(b), .Y(y),
);
endmodule
EOT
equiv_opt -assert opt_expr -fine
design -load postopt
select -assert-none t:$not
design -reset
read_verilog <<EOT
module test(input [1:0] sel, input [0:3] data, output out);
assign out = data[sel];
endmodule
EOT
equiv_opt -assert opt -full
design -load postopt
select -assert-none t:$sub t:$add t:$alu
design -reset
read_verilog <<EOT
module test(input sel, input [0:1] data, output out);
assign out = data[sel];
endmodule
EOT
equiv_opt -assert opt -full
design -load postopt
select -assert-none t:$sub t:$add t:$alu