mirror of https://github.com/YosysHQ/yosys.git
Merge d25171806b into b864f70e52
This commit is contained in:
commit
55a23b2f4d
|
|
@ -55,6 +55,7 @@ struct WreduceWorker
|
||||||
ModIndex mi;
|
ModIndex mi;
|
||||||
|
|
||||||
std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells;
|
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;
|
std::set<SigBit> work_queue_bits;
|
||||||
pool<SigBit> keep_bits;
|
pool<SigBit> keep_bits;
|
||||||
FfInitVals initvals;
|
FfInitVals initvals;
|
||||||
|
|
@ -78,6 +79,8 @@ struct WreduceWorker
|
||||||
for (int i = GetSize(sig_y)-1; i >= 0; i--)
|
for (int i = GetSize(sig_y)-1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
auto info = mi.query(sig_y[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]))) {
|
if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_y[i]))) {
|
||||||
bits_removed.push_back(State::Sx);
|
bits_removed.push_back(State::Sx);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -393,6 +396,8 @@ struct WreduceWorker
|
||||||
break;
|
break;
|
||||||
|
|
||||||
auto info = mi.query(bit);
|
auto info = mi.query(bit);
|
||||||
|
if (info == nullptr)
|
||||||
|
return;
|
||||||
if (info->is_output || GetSize(info->ports) > 1)
|
if (info->is_output || GetSize(info->ports) > 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -457,63 +462,87 @@ struct WreduceWorker
|
||||||
return count;
|
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()
|
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;
|
SigMap init_attr_sigmap = mi.sigmap;
|
||||||
initvals.set(&init_attr_sigmap, module);
|
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()) {
|
for (auto w : module->wires()) {
|
||||||
if (w->get_bool_attribute(ID::keep))
|
if (w->get_bool_attribute(ID::keep))
|
||||||
for (auto bit : mi.sigmap(w))
|
for (auto bit : mi.sigmap(w))
|
||||||
keep_bits.insert(bit);
|
keep_bits.insert(bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto c : module->selected_cells())
|
while (!work_queue_cells.empty() || !work_queue_wires.empty())
|
||||||
work_queue_cells.insert(c);
|
|
||||||
|
|
||||||
while (!work_queue_cells.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();
|
work_queue_bits.clear();
|
||||||
for (auto c : work_queue_cells)
|
for (auto c : work_queue_cells)
|
||||||
run_cell(c);
|
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();
|
work_queue_cells.clear();
|
||||||
for (auto bit : work_queue_bits)
|
for (auto bit : work_queue_bits)
|
||||||
for (auto port : mi.query_ports(bit))
|
for (auto port : mi.query_ports(bit))
|
||||||
if (module->selected(port.cell))
|
if (module->selected(port.cell))
|
||||||
work_queue_cells.insert(port.cell);
|
work_queue_cells.insert(port.cell);
|
||||||
}
|
|
||||||
|
|
||||||
pool<SigSpec> complete_wires;
|
// Get next batch of wires to process
|
||||||
for (auto w : module->wires())
|
work_queue_wires.clear();
|
||||||
complete_wires.insert(mi.sigmap(w));
|
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())
|
// Reload module
|
||||||
{
|
mi.reload_module();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue