Merge pull request #182 from Silimate/opt_compact_prefix_fix1

Fix opt_compact_prefix up
This commit is contained in:
Akash Levy 2026-06-09 01:57:52 -07:00 committed by GitHub
commit a96494eef1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 205 additions and 27 deletions

View File

@ -60,9 +60,22 @@ struct OptCompactPrefixWorker
}
}
Wire *port(const char *name)
vector<Wire *> input_ports()
{
return module->wire(RTLIL::escape_id(name));
vector<Wire *> ports;
for (auto wire : module->wires())
if (wire->port_input)
ports.push_back(wire);
return ports;
}
vector<Wire *> output_ports()
{
vector<Wire *> ports;
for (auto wire : module->wires())
if (wire->port_output)
ports.push_back(wire);
return ports;
}
int count_cells(IdString type)
@ -195,19 +208,36 @@ struct OptCompactPrefixWorker
return result;
}
bool bmux_selects_stay_in_range(Wire *data, int loop_width)
int output_bits_controlled_by(Wire *control, Wire *output)
{
bool saw_data_bmux = false;
pool<int> bits;
for (auto cell : module->cells()) {
if (cell->type != ID($bmux))
if (cell->type != ID($mux))
continue;
SigSpec sel = sigmap(cell->getPort(ID::S));
if (GetSize(sel) != 1 || sel[0].wire != control)
continue;
for (auto bit : sigmap(cell->getPort(ID::Y)))
if (bit.wire == output)
bits.insert(bit.offset);
}
return GetSize(bits);
}
bool indexed_reads_stay_in_range(Wire *data, int loop_width)
{
bool saw_data_read = false;
for (auto cell : module->cells()) {
if (!cell->type.in(ID($bmux), ID($shiftx)))
continue;
if (sigmap(cell->getPort(ID::A)) != sigmap(SigSpec(data)))
continue;
saw_data_bmux = true;
if (eval_sig_at_zero(cell->getPort(ID::S)) >= loop_width)
saw_data_read = true;
IdString select_port = cell->type == ID($bmux) ? ID::S : ID::B;
if (eval_sig_at_zero(cell->getPort(select_port)) >= loop_width)
return false;
}
return saw_data_bmux;
return saw_data_read;
}
SigSpec zext(SigSpec sig, int width)
@ -311,12 +341,12 @@ struct OptCompactPrefixWorker
bool rewrite_forward_dense_pack()
{
Wire *sig = port("sig");
Wire *sig2 = port("sig2");
if (!sig || !sig2)
return false;
if (!sig->port_input || !sig2->port_output)
vector<Wire *> inputs = input_ports();
vector<Wire *> outputs = output_ports();
if (GetSize(inputs) != 1 || GetSize(outputs) != 1)
return false;
Wire *sig = inputs[0];
Wire *sig2 = outputs[0];
if (GetSize(sig) != GetSize(sig2))
return false;
if (GetSize(sig) < 4 || GetSize(sig) > max_width)
@ -325,8 +355,6 @@ struct OptCompactPrefixWorker
return false;
if (count_binop_const(ID($add), 1) < GetSize(sig) - 2)
return false;
if (count_cells(ID($shl)) < GetSize(sig) - 2)
return false;
if (count_cells(ID($mux)) < GetSize(sig))
return false;
if (!eval_sig_is_zero(SigSpec(sig2)))
@ -357,29 +385,45 @@ struct OptCompactPrefixWorker
bool rewrite_reverse_suffix_read()
{
Wire *disable = port("disable_in");
Wire *data = port("data_in");
Wire *mask = port("mask");
if (!disable || !data || !mask)
vector<Wire *> inputs = input_ports();
vector<Wire *> outputs = output_ports();
if (GetSize(inputs) != 2 || GetSize(outputs) != 1)
return false;
if (!disable->port_input || !data->port_input || !mask->port_output)
return false;
if (GetSize(disable) != GetSize(data) || GetSize(mask) != GetSize(data))
return false;
if (GetSize(module->ports) != 3)
Wire *mask = outputs[0];
if (GetSize(inputs[0]) != GetSize(inputs[1]) || GetSize(mask) != GetSize(inputs[0]))
return false;
int dec_count = std::max(count_binop_const(ID($sub), 1),
count_binop_const(ID($add), -1));
int loop_width = dec_count + 1;
if (loop_width < 4 || loop_width > max_width || loop_width > GetSize(data))
return false;
if (count_cells(ID($mux)) < loop_width)
return false;
if (has_binop_const_other_than(ID($sub), 1) ||
has_binop_const_other_than(ID($add), -1))
return false;
if (!bmux_selects_stay_in_range(data, loop_width))
Wire *disable = nullptr;
int controlled_width = 0;
for (auto input : inputs) {
int n = output_bits_controlled_by(input, mask);
if (n == 0)
continue;
if (disable != nullptr)
return false;
disable = input;
controlled_width = n;
}
if (disable == nullptr)
return false;
if (controlled_width > 0)
loop_width = controlled_width;
if (loop_width < 4 || loop_width > max_width || loop_width > GetSize(mask))
return false;
if (dec_count < loop_width - 1)
return false;
Wire *data = (inputs[0] == disable) ? inputs[1] : inputs[0];
if (!indexed_reads_stay_in_range(data, loop_width))
return false;
if (!eval_sig_is_zero(SigSpec(mask)))
return false;

View File

@ -114,6 +114,23 @@ select -assert-count 32 t:$gt
design -reset
log -pop
log -header "Renamed ports: forward dense pack"
log -push
design -reset
verific -cfg veri_optimize_wide_selector 1
verific -cfg db_infer_wide_muxes_post_elaboration 0
read -sv opt_compact_prefix_renamed.sv
verific -import opt_compact_prefix_pack_renamed
proc; opt_clean
opt_compact_prefix
opt_clean
select -assert-none t:$shl
select -assert-none t:$mux
select -assert-count 7 t:$add
select -assert-count 8 t:$gt
design -reset
log -pop
log -header "Exact regression size: 16-entry reverse suffix read"
log -push
design -reset
@ -131,6 +148,53 @@ select -assert-min 1 t:$eq
design -reset
log -pop
log -header "Renamed ports: reverse suffix read"
log -push
design -reset
verific -cfg veri_optimize_wide_selector 1
verific -cfg db_infer_wide_muxes_post_elaboration 0
read -sv opt_compact_prefix_renamed.sv
verific -import opt_compact_prefix_sub_renamed
proc; opt_clean
opt_compact_prefix
opt_clean
select -assert-none t:$sub
select -assert-none t:$mux
select -assert-min 1 t:$add
select -assert-min 1 t:$eq
design -reset
log -pop
log -header "Yosys frontend: forward dense pack"
log -push
design -reset
read_verilog -sv opt_compact_prefix_yosys_frontend.v
hierarchy -top opt_compact_prefix_yosys_pack
proc; opt_clean
opt_compact_prefix
opt_clean
select -assert-none t:$shl
select -assert-none t:$mux
select -assert-count 7 t:$add
select -assert-count 8 t:$gt
design -reset
log -pop
log -header "Yosys frontend: reverse suffix read"
log -push
design -reset
read_verilog -sv opt_compact_prefix_yosys_frontend.v
hierarchy -top opt_compact_prefix_yosys_sub
proc; opt_clean
opt_compact_prefix
opt_clean
select -assert-none t:$sub
select -assert-none t:$mux
select -assert-min 1 t:$add
select -assert-min 1 t:$eq
design -reset
log -pop
log -header "Reverse suffix read with add-by-minus-one decrement"
log -push
design -reset

View File

@ -0,0 +1,32 @@
module opt_compact_prefix_pack_renamed (
input logic [7:0] in_bits,
output logic [7:0] packed_bits
);
always_comb begin
packed_bits = '0;
for (int I = 0, indx = 0; I < 8; I++) begin
if (in_bits[I]) begin
packed_bits[indx] = in_bits[I];
indx += 1;
end
end
end
endmodule
module opt_compact_prefix_sub_renamed (
input logic [15:0] stall_vec,
input logic [15:0] payload_vec,
output logic [15:0] allow_mask
);
always_comb begin
allow_mask = '0;
for (int I = 8, indx = 8; I > 0; I--) begin
if (stall_vec[I-1]) begin
allow_mask[I-1] = 1'b0;
end else begin
allow_mask[I-1] = payload_vec[indx-1];
indx = indx - 1;
end
end
end
endmodule

View File

@ -0,0 +1,38 @@
module opt_compact_prefix_yosys_pack (
input wire [7:0] in_bits,
output reg [7:0] packed_bits
);
integer I;
integer indx;
always @* begin
packed_bits = 8'b0;
indx = 0;
for (I = 0; I < 8; I = I + 1) begin
if (in_bits[I]) begin
packed_bits[indx] = in_bits[I];
indx = indx + 1;
end
end
end
endmodule
module opt_compact_prefix_yosys_sub (
input wire [15:0] stall_vec,
input wire [15:0] payload_vec,
output reg [15:0] allow_mask
);
integer I;
integer indx;
always @* begin
allow_mask = 16'b0;
indx = 8;
for (I = 8; I > 0; I = I - 1) begin
if (stall_vec[I-1]) begin
allow_mask[I-1] = 1'b0;
end else begin
allow_mask[I-1] = payload_vec[indx-1];
indx = indx - 1;
end
end
end
endmodule