Replace suitable (2^k-1)-x with ~x.

This commit is contained in:
nella 2026-06-10 11:29:55 +02:00
parent 8eb3133076
commit d52670e58b
2 changed files with 69 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