3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-03-02 03:36:56 +00:00

opt_clean: refactor

This commit is contained in:
Emil J. Tywoniak 2026-02-24 12:54:03 +01:00
parent 930bd3acc5
commit 5d3b3ff18d
4 changed files with 62 additions and 38 deletions

View file

@ -33,7 +33,7 @@ unsigned int hash_bit(const SigBit &bit) {
return static_cast<unsigned int>(hash_ops<SigBit>::hash(bit).yield());
}
void rmunused_module_cells(Module *module, ParallelDispatchThreadPool::Subpool &subpool, bool verbose, CleanRunContext &clean_ctx, keep_cache_t &keep_cache)
void rmunused_module_cells(Module *module, ParallelDispatchThreadPool::Subpool &subpool, CleanRunContext &clean_ctx)
{
SigMap sigmap(module);
FfInitVals ffinit;
@ -134,7 +134,7 @@ void rmunused_module_cells(Module *module, ParallelDispatchThreadPool::Subpool &
// Prepare "input cone" traversal from memory to write port or meminit as mem2cells
// Also check driver conflicts
// Also mark cells unused to true unless keep (we override this later)
subpool.run([&sigmap, &raw_sigmap, &keep_cache, const_module, &mem2cells_vector, &driver_driver_logs, &keep_wires, &cell_queue, &wire2driver_builder, &clean_ctx, &unused](const ParallelDispatchThreadPool::RunCtx &ctx) {
subpool.run([&sigmap, &raw_sigmap, const_module, &mem2cells_vector, &driver_driver_logs, &keep_wires, &cell_queue, &wire2driver_builder, &clean_ctx, &unused](const ParallelDispatchThreadPool::RunCtx &ctx) {
for (int i : ctx.item_range(const_module->cells_size())) {
Cell *cell = const_module->cell_at(i);
if (cell->type.in(ID($memwr), ID($memwr_v2), ID($meminit), ID($meminit_v2)))
@ -157,7 +157,7 @@ void rmunused_module_cells(Module *module, ParallelDispatchThreadPool::Subpool &
wire2driver_builder.insert(ctx, {{bit, i}, hash_bit(bit)});
}
}
bool keep = keep_cache.query(cell);
bool keep = clean_ctx.keep_cache.query(cell);
unused[i].store(!keep, std::memory_order_relaxed);
if (keep)
cell_queue.push(ctx, i);
@ -267,7 +267,7 @@ void rmunused_module_cells(Module *module, ParallelDispatchThreadPool::Subpool &
}
for (auto cell : unused_cells) {
if (verbose)
if (clean_ctx.flags.verbose)
log_debug(" removing unused `%s' cell `%s'.\n", cell->type, cell->name);
module->design->scratchpad_set_bool("opt.did_something", true);
if (cell->is_builtin_ff())
@ -280,7 +280,7 @@ void rmunused_module_cells(Module *module, ParallelDispatchThreadPool::Subpool &
if (!mem_unused[it.second].load(std::memory_order_relaxed))
continue;
RTLIL::IdString id(it.first);
if (verbose)
if (clean_ctx.flags.verbose)
log_debug(" removing unused memory `%s'.\n", id.unescape());
delete module->memories.at(id);
module->memories.erase(id);

View file

@ -34,21 +34,21 @@ PRIVATE_NAMESPACE_BEGIN
using RTLIL::id2cstr;
void rmunused_module(RTLIL::Module *module, ParallelDispatchThreadPool &thread_pool, bool purge_mode, bool verbose, bool rminit, CleanRunContext &clean_ctx, keep_cache_t &keep_cache)
void rmunused_module(RTLIL::Module *module, bool rminit, CleanRunContext &clean_ctx)
{
if (verbose)
if (clean_ctx.flags.verbose)
log("Finding unused cells or wires in module %s..\n", module->name);
// Use no more than one worker per thousand cells, rounded down, so
// we only start multithreading with at least 2000 cells.
int num_worker_threads = ThreadPool::work_pool_size(0, module->cells_size(), 1000);
ParallelDispatchThreadPool::Subpool subpool(thread_pool, num_worker_threads);
remove_temporary_cells(module, subpool, verbose);
rmunused_module_cells(module, subpool, verbose, clean_ctx, keep_cache);
while (rmunused_module_signals(module, subpool, purge_mode, verbose, clean_ctx)) { }
ParallelDispatchThreadPool::Subpool subpool(clean_ctx.thread_pool, num_worker_threads);
remove_temporary_cells(module, subpool, clean_ctx.flags.verbose);
rmunused_module_cells(module, subpool, clean_ctx);
while (rmunused_module_signals(module, subpool, clean_ctx)) { }
if (rminit && rmunused_module_init(module, subpool, verbose))
while (rmunused_module_signals(module, subpool, purge_mode, verbose, clean_ctx)) { }
if (rminit && rmunused_module_init(module, subpool, clean_ctx.flags.verbose))
while (rmunused_module_signals(module, subpool, clean_ctx)) { }
}
struct OptCleanPass : public Pass {
OptCleanPass() : Pass("opt_clean", "remove unused cells and wires") { }
@ -97,9 +97,9 @@ struct OptCleanPass : public Pass {
keep_cache_t keep_cache(purge_mode, thread_pool, selected_modules);
{
CleanRunContext clean_ctx(design);
CleanRunContext clean_ctx(design, {purge_mode, true});
for (auto module : selected_modules)
rmunused_module(module, thread_pool, purge_mode, true, true, clean_ctx, keep_cache);
rmunused_module(module, true, clean_ctx);
clean_ctx.stats.log();
design->optimize();
@ -143,20 +143,10 @@ struct CleanPass : public Pass {
}
extra_args(args, argidx, design);
std::vector<RTLIL::Module*> selected_modules;
for (auto module : design->selected_unboxed_whole_modules())
if (!module->has_processes())
selected_modules.push_back(module);
int thread_pool_size = 0;
for (RTLIL::Module *m : selected_modules)
thread_pool_size = std::max(thread_pool_size, ThreadPool::work_pool_size(0, m->cells_size(), 1000));
ParallelDispatchThreadPool thread_pool(thread_pool_size);
keep_cache_t keep_cache(purge_mode, thread_pool, selected_modules);
{
CleanRunContext clean_ctx(design);
for (auto module : selected_modules)
rmunused_module(module, thread_pool, purge_mode, ys_debug(), true, clean_ctx, keep_cache);
CleanRunContext clean_ctx(design, {purge_mode, ys_debug()});
for (auto module : clean_ctx.selected_modules)
rmunused_module(module, true, clean_ctx);
log_suppressed();
clean_ctx.stats.log();

View file

@ -22,6 +22,7 @@
#include "kernel/threading.h"
#include "kernel/celltypes.h"
#include "kernel/yosys_common.h"
#include "passes/opt/opt_clean/keep_cache.h"
#ifndef OPT_CLEAN_SHARED_H
#define OPT_CLEAN_SHARED_H
@ -47,27 +48,60 @@ struct RmStats {
}
};
struct Flags {
bool purge = false;
bool verbose = false;
};
struct CleanRunContext {
CellTypes ct_reg;
CellTypes ct_all;
RmStats stats;
CleanRunContext(RTLIL::Design* design) {
ParallelDispatchThreadPool thread_pool;
std::vector<RTLIL::Module*> selected_modules;
keep_cache_t keep_cache;
Flags flags;
private:
// Helper to compute thread pool size
static int compute_thread_pool_size(RTLIL::Design* design) {
int thread_pool_size = 0;
for (auto module : design->selected_unboxed_whole_modules())
if (!module->has_processes())
thread_pool_size = std::max(thread_pool_size,
ThreadPool::work_pool_size(0, module->cells_size(), 1000));
return thread_pool_size;
}
static std::vector<RTLIL::Module*> get_selected_modules(RTLIL::Design* design) {
std::vector<RTLIL::Module*> modules;
for (auto module : design->selected_unboxed_whole_modules())
if (!module->has_processes())
modules.push_back(module);
return modules;
}
public:
CleanRunContext(RTLIL::Design* design, Flags f)
: thread_pool(compute_thread_pool_size(design)),
selected_modules(get_selected_modules(design)),
keep_cache(f.purge, thread_pool, selected_modules),
flags(f)
{
ct_reg.setup_internals_mem();
ct_reg.setup_internals_anyinit();
ct_reg.setup_stdcells_mem();
ct_all.setup(design);
}
~CleanRunContext() {
ct_reg.clear();
ct_all.clear();
}
};
struct keep_cache_t;
void remove_temporary_cells(RTLIL::Module *module, ParallelDispatchThreadPool::Subpool &subpool, bool verbose);
void rmunused_module_cells(Module *module, ParallelDispatchThreadPool::Subpool &subpool, bool verbose, CleanRunContext &clean_ctx, keep_cache_t &keep_cache);
bool rmunused_module_signals(RTLIL::Module *module, ParallelDispatchThreadPool::Subpool &subpool, bool purge_mode, bool verbose, CleanRunContext &clean_ctx);
void rmunused_module_cells(Module *module, ParallelDispatchThreadPool::Subpool &subpool, CleanRunContext &clean_ctx);
bool rmunused_module_signals(RTLIL::Module *module, ParallelDispatchThreadPool::Subpool &subpool, CleanRunContext &clean_ctx);
bool rmunused_module_init(RTLIL::Module *module, ParallelDispatchThreadPool::Subpool &subpool, bool verbose);
YOSYS_NAMESPACE_END

View file

@ -537,13 +537,13 @@ PRIVATE_NAMESPACE_END
YOSYS_NAMESPACE_BEGIN
bool rmunused_module_signals(RTLIL::Module *module, ParallelDispatchThreadPool::Subpool &subpool, bool purge_mode, bool verbose, CleanRunContext &clean_ctx)
bool rmunused_module_signals(RTLIL::Module *module, ParallelDispatchThreadPool::Subpool &subpool, CleanRunContext &clean_ctx)
{
// Passing actx to function == function does parallel work
// Not passing module as function argument == function does not modify module
// TODO the above sentence is false due to constness laundering in wire_at / cell_at
AnalysisContext actx(module, subpool);
SigConnKinds conn_kinds(purge_mode, actx, clean_ctx);
SigConnKinds conn_kinds(clean_ctx.flags.purge, actx, clean_ctx);
// Main thread's cached direct wires are retained and used later:
DirectWires direct_wires(conn_kinds.direct, actx.assign_map);
@ -565,17 +565,17 @@ bool rmunused_module_signals(RTLIL::Module *module, ParallelDispatchThreadPool::
fixup_update_ports(deferred.update_connections);
consume_inits(deferred.initialized_wires, actx.assign_map).apply_normalised_inits();
WireDeleter deleter(used, purge_mode, actx);
WireDeleter deleter(used, clean_ctx.flags.purge, actx);
used.clear(subpool);
deleter.commit_changes(module);
int deleted_and_unreported = deleter.delete_wires(module, verbose);
int deleted_and_unreported = deleter.delete_wires(module, clean_ctx.flags.verbose);
int deleted_total = GetSize(deleter.del_wires_queue);
clean_ctx.stats.count_rm_wires += deleted_total;
if (verbose && deleted_and_unreported)
if (clean_ctx.flags.verbose && deleted_and_unreported)
log_debug(" removed %d unused temporary wires.\n", deleted_and_unreported);
if (deleted_total)