From e4dde705dc18024c769deb6123f1a0d614556e36 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 28 Jan 2026 22:46:10 +0000 Subject: [PATCH] Pass the module `Subpool` to `rmunused_module_init` and parallelize that function --- passes/opt/opt_clean.cc | 134 +++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 62 deletions(-) diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 78546914d..c7874eeb3 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -590,79 +590,93 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos return !del_wires_queue.empty(); } -bool rmunused_module_init(RTLIL::Module *module, bool verbose) +bool rmunused_module_init(RTLIL::Module *module, ParallelDispatchThreadPool::Subpool &subpool, bool verbose) { - bool did_something = false; CellTypes fftypes; fftypes.setup_internals_mem(); SigMap sigmap(module); - dict qbits; - for (auto cell : module->cells()) - if (fftypes.cell_known(cell->type) && cell->hasPort(ID::Q)) - { - SigSpec sig = cell->getPort(ID::Q); - - for (int i = 0; i < GetSize(sig); i++) + const Module *const_module = module; + ShardedVector> results(subpool); + subpool.run([const_module, &fftypes, &results](const ParallelDispatchThreadPool::RunCtx &ctx) { + for (int i : ctx.item_range(const_module->cells_size())) { + RTLIL::Cell *cell = const_module->cell_at(i); + if (fftypes.cell_known(cell->type) && cell->hasPort(ID::Q)) { - SigBit bit = sig[i]; + SigSpec sig = cell->getPort(ID::Q); - if (bit.wire == nullptr || bit.wire->attributes.count(ID::init) == 0) - continue; + for (int i = 0; i < GetSize(sig); i++) + { + SigBit bit = sig[i]; - Const init = bit.wire->attributes.at(ID::init); + if (bit.wire == nullptr || bit.wire->attributes.count(ID::init) == 0) + continue; - if (i >= GetSize(init) || init[i] == State::Sx || init[i] == State::Sz) - continue; + Const init = bit.wire->attributes.at(ID::init); - sigmap.add(bit); - qbits[bit] = init[i]; - } - } + if (i >= GetSize(init) || init[i] == State::Sx || init[i] == State::Sz) + continue; - for (auto wire : module->wires()) - { - if (wire->attributes.count(ID::init) == 0) - continue; - - Const init = wire->attributes.at(ID::init); - - for (int i = 0; i < GetSize(wire) && i < GetSize(init); i++) - { - if (init[i] == State::Sx || init[i] == State::Sz) - continue; - - SigBit wire_bit = SigBit(wire, i); - SigBit mapped_wire_bit = sigmap(wire_bit); - - if (wire_bit == mapped_wire_bit) - goto next_wire; - - if (mapped_wire_bit.wire) { - if (qbits.count(mapped_wire_bit) == 0) - goto next_wire; - - if (qbits.at(mapped_wire_bit) != init[i]) - goto next_wire; - } - else { - if (mapped_wire_bit == State::Sx || mapped_wire_bit == State::Sz) - goto next_wire; - - if (mapped_wire_bit != init[i]) { - log_warning("Initial value conflict for %s resolving to %s but with init %s.\n", log_signal(wire_bit), log_signal(mapped_wire_bit), log_signal(init[i])); - goto next_wire; + results.insert(ctx, {bit, init[i]}); } } } + }); + dict qbits; + for (std::pair &p : results) { + sigmap.add(p.first); + qbits[p.first] = p.second; + } + ShardedVector wire_results(subpool); + subpool.run([const_module, &sigmap, &qbits, &wire_results](const ParallelDispatchThreadPool::RunCtx &ctx) { + for (int j : ctx.item_range(const_module->wires_size())) { + RTLIL::Wire *wire = const_module->wire_at(j); + if (wire->attributes.count(ID::init) == 0) + continue; + Const init = wire->attributes.at(ID::init); + + for (int i = 0; i < GetSize(wire) && i < GetSize(init); i++) + { + if (init[i] == State::Sx || init[i] == State::Sz) + continue; + + SigBit wire_bit = SigBit(wire, i); + SigBit mapped_wire_bit = sigmap(wire_bit); + + if (wire_bit == mapped_wire_bit) + goto next_wire; + + if (mapped_wire_bit.wire) { + if (qbits.count(mapped_wire_bit) == 0) + goto next_wire; + + if (qbits.at(mapped_wire_bit) != init[i]) + goto next_wire; + } + else { + if (mapped_wire_bit == State::Sx || mapped_wire_bit == State::Sz) + goto next_wire; + + if (mapped_wire_bit != init[i]) { + log_warning("Initial value conflict for %s resolving to %s but with init %s.\n", log_signal(wire_bit), log_signal(mapped_wire_bit), log_signal(init[i])); + goto next_wire; + } + } + } + wire_results.insert(ctx, wire); + + next_wire:; + } + }); + + bool did_something = false; + for (RTLIL::Wire *wire : wire_results) { if (verbose) log_debug(" removing redundant init attribute on %s.\n", log_id(wire)); - wire->attributes.erase(ID::init); did_something = true; - next_wire:; } if (did_something) @@ -749,7 +763,7 @@ void rmunused_module(RTLIL::Module *module, ParallelDispatchThreadPool &thread_p rmunused_module_cells(module, verbose, stats, keep_cache); while (rmunused_module_signals(module, purge_mode, verbose, stats)) { } - if (rminit && rmunused_module_init(module, verbose)) + if (rminit && rmunused_module_init(module, subpool, verbose)) while (rmunused_module_signals(module, purge_mode, verbose, stats)) { } } @@ -790,10 +804,9 @@ struct OptCleanPass : public Pass { extra_args(args, argidx, design); std::vector selected_modules; - for (auto module : design->selected_whole_modules_warn()) { + for (auto module : design->selected_whole_modules_warn()) if (!module->has_processes_warn()) 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)); @@ -807,9 +820,8 @@ struct OptCleanPass : public Pass { ct_all.setup(design); RmStats stats; - for (auto module : selected_modules) { + for (auto module : selected_modules) rmunused_module(module, thread_pool, purge_mode, true, true, stats, keep_cache); - } stats.log(); design->optimize(); @@ -855,10 +867,9 @@ struct CleanPass : public Pass { extra_args(args, argidx, design); std::vector selected_modules; - for (auto module : design->selected_unboxed_whole_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)); @@ -872,9 +883,8 @@ struct CleanPass : public Pass { ct_all.setup(design); RmStats stats; - for (auto module : selected_modules) { + for (auto module : selected_modules) rmunused_module(module, thread_pool, purge_mode, ys_debug(), true, stats, keep_cache); - } log_suppressed(); stats.log();