3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-01-17 07:56:26 +00:00
This commit is contained in:
nataliakokoromyti 2026-01-14 17:40:45 -08:00 committed by GitHub
commit 8d3b5ebe58
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 97 additions and 34 deletions

View file

@ -55,6 +55,7 @@ struct WreduceWorker
ModIndex mi;
std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells;
std::set<Wire*, IdString::compare_ptr_by_name<Wire>> work_queue_wires;
std::set<SigBit> work_queue_bits;
pool<SigBit> keep_bits;
FfInitVals initvals;
@ -78,6 +79,8 @@ struct WreduceWorker
for (int i = GetSize(sig_y)-1; i >= 0; i--)
{
auto info = mi.query(sig_y[i]);
if (info == nullptr)
return;
if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_y[i]))) {
bits_removed.push_back(State::Sx);
continue;
@ -393,6 +396,8 @@ struct WreduceWorker
break;
auto info = mi.query(bit);
if (info == nullptr)
return;
if (info->is_output || GetSize(info->ports) > 1)
break;
@ -457,63 +462,87 @@ struct WreduceWorker
return count;
}
void run_wire(Wire *w, pool<SigSpec> complete_wires)
{
int unused_top_bits = 0;
if (w->port_id > 0 || count_nontrivial_wire_attrs(w) > 0)
return;
for (int i = GetSize(w)-1; i >= 0; i--) {
SigBit bit(w, i);
auto info = mi.query(bit);
if (info == nullptr)
return;
if (info && (info->is_input || info->is_output || GetSize(info->ports) > 0))
break;
unused_top_bits++;
}
if (unused_top_bits == 0 || unused_top_bits == GetSize(w))
return;
if (complete_wires[mi.sigmap(w).extract(0, GetSize(w) - unused_top_bits)])
return;
log("Removed top %d bits (of %d) from wire %s.%s.\n", unused_top_bits, GetSize(w), log_id(module), log_id(w));
Wire *nw = module->addWire(module->uniquify(IdString(w->name.str() + "_wreduce")), GetSize(w) - unused_top_bits);
module->connect(nw, SigSpec(w).extract(0, GetSize(nw)));
module->swap_names(w, nw);
}
void run()
{
// create a copy as mi.sigmap will be updated as we process the module
// Create a copy as mi.sigmap will be updated as we process the module
SigMap init_attr_sigmap = mi.sigmap;
initvals.set(&init_attr_sigmap, module);
// Initialize cell work queue
for (auto c : module->selected_cells())
work_queue_cells.insert(c);
// Initialize wire work queue
for (auto w : module->selected_wires())
work_queue_wires.insert(w);
// Initialize keep bits
for (auto w : module->wires()) {
if (w->get_bool_attribute(ID::keep))
for (auto bit : mi.sigmap(w))
keep_bits.insert(bit);
}
for (auto c : module->selected_cells())
work_queue_cells.insert(c);
while (!work_queue_cells.empty())
while (!work_queue_cells.empty() || !work_queue_wires.empty())
{
// Initialize complete wires
pool<SigSpec> complete_wires;
for (auto w : module->wires())
complete_wires.insert(mi.sigmap(w));
// Run cells
work_queue_bits.clear();
for (auto c : work_queue_cells)
run_cell(c);
// Run wires
for (auto w : work_queue_wires)
run_wire(w, complete_wires);
// Get next batch of cells to process
work_queue_cells.clear();
for (auto bit : work_queue_bits)
for (auto port : mi.query_ports(bit))
if (module->selected(port.cell))
work_queue_cells.insert(port.cell);
}
pool<SigSpec> complete_wires;
for (auto w : module->wires())
complete_wires.insert(mi.sigmap(w));
// Get next batch of wires to process
work_queue_wires.clear();
for (auto bit : work_queue_bits)
if (bit.wire != NULL && module->selected(bit.wire))
work_queue_wires.insert(bit.wire);
for (auto w : module->selected_wires())
{
int unused_top_bits = 0;
if (w->port_id > 0 || count_nontrivial_wire_attrs(w) > 0)
continue;
for (int i = GetSize(w)-1; i >= 0; i--) {
SigBit bit(w, i);
auto info = mi.query(bit);
if (info && (info->is_input || info->is_output || GetSize(info->ports) > 0))
break;
unused_top_bits++;
}
if (unused_top_bits == 0 || unused_top_bits == GetSize(w))
continue;
if (complete_wires[mi.sigmap(w).extract(0, GetSize(w) - unused_top_bits)])
continue;
log("Removed top %d bits (of %d) from wire %s.%s.\n", unused_top_bits, GetSize(w), log_id(module), log_id(w));
Wire *nw = module->addWire(NEW_ID, GetSize(w) - unused_top_bits);
module->connect(nw, SigSpec(w).extract(0, GetSize(nw)));
module->swap_names(w, nw);
// Reload module
mi.reload_module();
}
}
};

View file

@ -0,0 +1,34 @@
# Ensure wreduce propagates width reductions across dependent cells.
read_verilog <<EOT
module top(input [7:0] a, input [7:0] b, input [3:0] c, output [3:0] y);
wire [8:0] sum_full;
wire [3:0] sum_trunc;
assign sum_full = a + b;
assign sum_trunc = sum_full[3:0];
assign y = sum_trunc + c;
endmodule
EOT
hierarchy -auto-top
proc
opt_expr
opt_clean
design -save gold
wreduce
opt_clean
# After wreduce, the first add should be reduced from 9 bits to 4 bits
select -assert-count 2 t:$add
select -assert-count 0 t:$add r:Y_WIDTH=9 %i
select -assert-count 2 t:$add r:Y_WIDTH=4 %i
design -stash reduced
design -import gold -as gold
design -import reduced -as reduced
miter -equiv -flatten -make_assert -make_outputs gold reduced miter
sat -verify -prove-asserts -show-ports miter