mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-20 14:15:49 +00:00
Merge branch 'main' into large_mem_fix
This commit is contained in:
commit
ff0014b925
3 changed files with 74 additions and 19 deletions
|
|
@ -1524,7 +1524,7 @@ struct HierarchyPass : public Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!conn.second.is_fully_const() || !w->port_input || w->port_output)
|
if (!conn.second.is_fully_const() || !w->port_input || w->port_output)
|
||||||
log_warning("Resizing cell port %s.%s.%s from %d bits to %d bits.\n", module, cell,
|
log("Resizing cell port %s.%s.%s from %d bits to %d bits.\n", module, cell,
|
||||||
conn.first.unescape(), GetSize(conn.second), GetSize(sig));
|
conn.first.unescape(), GetSize(conn.second), GetSize(sig));
|
||||||
cell->setPort(conn.first, sig);
|
cell->setPort(conn.first, sig);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -961,6 +961,22 @@ struct OptCompactPrefixWorker : CutRegionWorker
|
||||||
true, std::max(8192, max_width * max_width * 4), max_width * (max_width + 8));
|
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()
|
void run()
|
||||||
{
|
{
|
||||||
if (module->has_processes_warn())
|
if (module->has_processes_warn())
|
||||||
|
|
@ -990,6 +1006,8 @@ struct OptCompactPrefixWorker : CutRegionWorker
|
||||||
}
|
}
|
||||||
if (root_claimed(root.sig))
|
if (root_claimed(root.sig))
|
||||||
continue;
|
continue;
|
||||||
|
if (root_driver_emitted(root.sig))
|
||||||
|
continue;
|
||||||
|
|
||||||
int width = GetSize(root.sig);
|
int width = GetSize(root.sig);
|
||||||
// Wide roots (>62) are valid forward-pack candidates; the
|
// Wide roots (>62) are valid forward-pack candidates; the
|
||||||
|
|
@ -1505,28 +1523,63 @@ struct OptCompactPrefixPass : public Pass
|
||||||
int total_removed = 0;
|
int total_removed = 0;
|
||||||
int total_emitted = 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()) {
|
for (auto module : design->selected_modules()) {
|
||||||
OptCompactPrefixWorker worker(module, max_width);
|
for (int sweep = 0; sweep < max_sweeps; sweep++) {
|
||||||
if (walk_budget > 0)
|
pool<Cell *> before;
|
||||||
worker.walk_budget = walk_budget;
|
for (auto c : module->cells())
|
||||||
if (eval_budget > 0)
|
before.insert(c);
|
||||||
worker.eval_budget = eval_budget;
|
|
||||||
if (attempt_budget > 0)
|
OptCompactPrefixWorker worker(module, max_width);
|
||||||
worker.attempt_budget = attempt_budget;
|
if (walk_budget > 0)
|
||||||
worker.run();
|
worker.walk_budget = walk_budget;
|
||||||
total_forward += worker.forward_rewrites;
|
if (eval_budget > 0)
|
||||||
total_reverse += worker.reverse_rewrites;
|
worker.eval_budget = eval_budget;
|
||||||
total_modulo += worker.modulo_rewrites;
|
if (attempt_budget > 0)
|
||||||
total_removed += worker.old_cells_removed;
|
worker.attempt_budget = attempt_budget;
|
||||||
total_emitted += worker.new_cells_emitted;
|
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); "
|
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",
|
"removed %d old cell(s), emitted %d new cell(s).\n",
|
||||||
total_forward, total_reverse, total_modulo, total_removed, total_emitted);
|
total_forward, total_reverse, total_modulo, total_removed, total_emitted);
|
||||||
|
|
||||||
if (total_forward || total_reverse || total_modulo)
|
|
||||||
Yosys::run_pass("clean -purge");
|
|
||||||
}
|
}
|
||||||
} OptCompactPrefixPass;
|
} OptCompactPrefixPass;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,9 @@ endmodule
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
# Mixed implicit and explicit 2
|
# 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);
|
module add(input [7:0] a, input [7:0] b, output [7:0] q);
|
||||||
assign q = a + b;
|
assign q = a + b;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
@ -121,4 +123,4 @@ module top(input [7:0] a, input [9:0] b, output [7:0] q);
|
||||||
add add_i(.b, .*);
|
add add_i(.b, .*);
|
||||||
endmodule
|
endmodule
|
||||||
EOT
|
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