mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-15 11:45:41 +00:00
Merge pull request #193 from Silimate/opt_compact_prefix_fix3
opt_compact_prefix fix 3
This commit is contained in:
commit
3876f53c73
2 changed files with 73 additions and 18 deletions
|
|
@ -961,6 +961,22 @@ struct OptCompactPrefixWorker : CutRegionWorker
|
|||
true, std::max(8192, max_width * max_width * 4), max_width * (max_width + 8));
|
||||
}
|
||||
|
||||
// True if any bit of `sig` is driven by a cell this pass emitted on an
|
||||
// earlier fixpoint sweep (tagged in execute()). The emitted compaction
|
||||
// logic still fingerprints as the same function, so this guard stops the
|
||||
// outer fixpoint loop from re-rewriting its own output indefinitely.
|
||||
bool root_driver_emitted(const SigSpec &sig)
|
||||
{
|
||||
for (auto bit : sigmap(sig)) {
|
||||
if (!bit.wire)
|
||||
continue;
|
||||
Cell *drv = bit_to_driver.at(bit, nullptr);
|
||||
if (drv && drv->get_bool_attribute(ID(opt_compact_prefix_emitted)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
if (module->has_processes_warn())
|
||||
|
|
@ -990,6 +1006,8 @@ struct OptCompactPrefixWorker : CutRegionWorker
|
|||
}
|
||||
if (root_claimed(root.sig))
|
||||
continue;
|
||||
if (root_driver_emitted(root.sig))
|
||||
continue;
|
||||
|
||||
int width = GetSize(root.sig);
|
||||
// Wide roots (>62) are valid forward-pack candidates; the
|
||||
|
|
@ -1505,28 +1523,63 @@ struct OptCompactPrefixPass : public Pass
|
|||
int total_removed = 0;
|
||||
int total_emitted = 0;
|
||||
|
||||
// Overlapping compaction loops can share post-synthesis logic (e.g. one
|
||||
// loop's start mask feeding the other loop's cone), so a single sweep
|
||||
// claims the first region and masks the second. Iterate each module to
|
||||
// a fixpoint: rewrite, tag the freshly-emitted cells, clean, and re-scan
|
||||
// until a sweep finds nothing new. The tag (consumed by
|
||||
// root_driver_emitted) stops the next sweep from re-matching this pass's
|
||||
// own output, which still fingerprints as the same compaction function.
|
||||
const int max_sweeps = 16;
|
||||
for (auto module : design->selected_modules()) {
|
||||
OptCompactPrefixWorker worker(module, max_width);
|
||||
if (walk_budget > 0)
|
||||
worker.walk_budget = walk_budget;
|
||||
if (eval_budget > 0)
|
||||
worker.eval_budget = eval_budget;
|
||||
if (attempt_budget > 0)
|
||||
worker.attempt_budget = attempt_budget;
|
||||
worker.run();
|
||||
total_forward += worker.forward_rewrites;
|
||||
total_reverse += worker.reverse_rewrites;
|
||||
total_modulo += worker.modulo_rewrites;
|
||||
total_removed += worker.old_cells_removed;
|
||||
total_emitted += worker.new_cells_emitted;
|
||||
for (int sweep = 0; sweep < max_sweeps; sweep++) {
|
||||
pool<Cell *> before;
|
||||
for (auto c : module->cells())
|
||||
before.insert(c);
|
||||
|
||||
OptCompactPrefixWorker worker(module, max_width);
|
||||
if (walk_budget > 0)
|
||||
worker.walk_budget = walk_budget;
|
||||
if (eval_budget > 0)
|
||||
worker.eval_budget = eval_budget;
|
||||
if (attempt_budget > 0)
|
||||
worker.attempt_budget = attempt_budget;
|
||||
worker.run();
|
||||
|
||||
total_forward += worker.forward_rewrites;
|
||||
total_reverse += worker.reverse_rewrites;
|
||||
total_modulo += worker.modulo_rewrites;
|
||||
total_removed += worker.old_cells_removed;
|
||||
total_emitted += worker.new_cells_emitted;
|
||||
|
||||
if (worker.forward_rewrites + worker.reverse_rewrites +
|
||||
worker.modulo_rewrites == 0)
|
||||
break;
|
||||
if (sweep == max_sweeps - 1)
|
||||
log_warning("opt_compact_prefix: fixpoint not reached for module %s "
|
||||
"after %d sweeps; some compaction opportunities may remain.\n",
|
||||
log_id(module), max_sweeps);
|
||||
|
||||
// Tag the cells emitted by this sweep so the next sweep skips
|
||||
// them, then drop the now-dangling old cone so the masked
|
||||
// sibling region becomes visible. Scope the clean to the module
|
||||
// under rewrite so untouched modules keep their dangling cells
|
||||
// until their own sweep, matching the original single-call run.
|
||||
for (auto c : module->cells())
|
||||
if (!before.count(c))
|
||||
c->set_bool_attribute(ID(opt_compact_prefix_emitted));
|
||||
Pass::call_on_module(design, module, "clean -purge");
|
||||
}
|
||||
}
|
||||
|
||||
// Drop the internal bookkeeping tag so it never leaks into the netlist.
|
||||
for (auto module : design->modules())
|
||||
for (auto c : module->cells())
|
||||
c->attributes.erase(ID(opt_compact_prefix_emitted));
|
||||
|
||||
log("Rewrote %d forward pack(s), %d reverse suffix read(s), %d modulo decimation(s); "
|
||||
"removed %d old cell(s), emitted %d new cell(s).\n",
|
||||
total_forward, total_reverse, total_modulo, total_removed, total_emitted);
|
||||
|
||||
if (total_forward || total_reverse || total_modulo)
|
||||
Yosys::run_pass("clean -purge");
|
||||
}
|
||||
} OptCompactPrefixPass;
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,9 @@ endmodule
|
|||
EOT
|
||||
|
||||
# Mixed implicit and explicit 2
|
||||
(${YOSYS} -f "verilog -sv" -qp "prep -flatten -top top; select -assert-count 1 t:\$add" - <<EOT
|
||||
# Port resize is now an informational log() (see "Reduce port resize to warning"),
|
||||
# which -q suppresses, so run without -q to observe the message.
|
||||
(${YOSYS} -f "verilog -sv" -p "prep -flatten -top top; select -assert-count 1 t:\$add" - <<EOT
|
||||
module add(input [7:0] a, input [7:0] b, output [7:0] q);
|
||||
assign q = a + b;
|
||||
endmodule
|
||||
|
|
@ -121,4 +123,4 @@ module top(input [7:0] a, input [9:0] b, output [7:0] q);
|
|||
add add_i(.b, .*);
|
||||
endmodule
|
||||
EOT
|
||||
) 2>&1 | grep -F "Warning: Resizing cell port top.add_i.b from 10 bits to 8 bits." > /dev/null
|
||||
) 2>&1 | grep -F "Resizing cell port top.add_i.b from 10 bits to 8 bits." > /dev/null
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue