From 4f6a1539617e89fb11897afe7a3be90e3c10f321 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 27 Aug 2024 08:19:17 -0700 Subject: [PATCH] Working tree balance pass --- Makefile | 5 +++++ passes/cmds/splitfanout.cc | 2 ++ passes/opt/muxpack.cc | 37 ++++++++++++++++++++++------------ passes/opt/opt_balance_tree.cc | 25 +++++++++++++++-------- passes/techmap/Makefile.inc | 5 +++-- 5 files changed, 51 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 2bf947bf8..2846be497 100644 --- a/Makefile +++ b/Makefile @@ -702,6 +702,8 @@ include $(YOSYS_SRC)/frontends/rtlil/Makefile.inc include $(YOSYS_SRC)/frontends/ast/Makefile.inc include $(YOSYS_SRC)/frontends/blif/Makefile.inc +include $(YOSYS_SRC)/frontends/liberty/Makefile.inc + OBJS += passes/hierarchy/hierarchy.o OBJS += passes/cmds/select.o OBJS += passes/cmds/show.o @@ -710,8 +712,11 @@ OBJS += passes/cmds/cover.o OBJS += passes/cmds/design.o OBJS += passes/cmds/plugin.o +OBJS += passes/cmds/clean_zerowidth.o OBJS += passes/cmds/splitfanout.o +include $(YOSYS_SRC)/passes/memory/Makefile.inc + include $(YOSYS_SRC)/passes/proc/Makefile.inc include $(YOSYS_SRC)/passes/opt/Makefile.inc include $(YOSYS_SRC)/passes/techmap/Makefile.inc diff --git a/passes/cmds/splitfanout.cc b/passes/cmds/splitfanout.cc index 8b844564d..83c103819 100644 --- a/passes/cmds/splitfanout.cc +++ b/passes/cmds/splitfanout.cc @@ -191,6 +191,8 @@ struct SplitfanoutPass : public Pass { log("Split %d cells in module '%s' into %d copies based on fanout.\n", count_split_pre, log_id(module), count_split_post); } + + Pass::call(design, "clean"); } } SplitfanoutPass; diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index d6dae37ce..3f7ee7221 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -31,9 +31,9 @@ struct ExclusiveDatabase dict>> sig_cmp_prev; - ExclusiveDatabase(Module *module, const SigMap &sigmap, bool ignore_excl) : module(module), sigmap(sigmap) + ExclusiveDatabase(Module *module, const SigMap &sigmap, bool assume_excl) : module(module), sigmap(sigmap) { - if (ignore_excl) return; + if (assume_excl) return; SigSpec const_sig, nonconst_sig; SigBit y_port; pool reduce_or; @@ -181,7 +181,7 @@ struct MuxpackWorker } } - void find_chain_start_cells(bool ignore_excl) + void find_chain_start_cells(bool assume_excl) { for (auto cell : candidate_cells) { @@ -211,7 +211,7 @@ struct MuxpackWorker log_assert(prev_cell); SigSpec s_sig = sigmap(cell->getPort(ID::S)); s_sig.append(sigmap(prev_cell->getPort(ID::S))); - if (!ignore_excl && !excl_db.query(s_sig)) + if (!assume_excl && !excl_db.query(s_sig)) goto start_cell; } @@ -310,11 +310,11 @@ struct MuxpackWorker candidate_cells.clear(); } - MuxpackWorker(Module *module, bool ignore_excl) : - module(module), sigmap(module), mux_count(0), pmux_count(0), excl_db(module, sigmap, ignore_excl) + MuxpackWorker(Module *module, bool assume_excl) : + module(module), sigmap(module), mux_count(0), pmux_count(0), excl_db(module, sigmap, assume_excl) { make_sig_chain_next_prev(); - find_chain_start_cells(ignore_excl); + find_chain_start_cells(assume_excl); for (auto c : chain_start_cells) { vector chain = create_chain(c); @@ -341,32 +341,43 @@ struct MuxpackPass : public Pass { log("whose select lines are driven by '$eq' cells with other such cells if it can be\n"); log("certain that their select inputs are mutually exclusive.\n"); log("\n"); - log(" -ignore_excl\n"); - log(" ignore mutually exclusive constraint when packing (less conservative)\n"); + log(" -splitfanout\n"); + log(" run splitfanout pass first\n"); + log("\n"); + log(" -assume_excl\n"); + log(" assume mutually exclusive constraint when packing (may result in inequivalence)\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) override { - bool ignore_excl = false; + bool splitfanout = false; + bool assume_excl = false; log_header(design, "Executing MUXPACK pass ($mux cell cascades to $pmux).\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-ignore_excl") { - ignore_excl = true; + if (args[argidx] == "-splitfanout") { + splitfanout = true; + continue; + } + if (args[argidx] == "-assume_excl") { + assume_excl = true; continue; } break; } extra_args(args, argidx, design); + if (splitfanout) + Pass::call(design, "splitfanout t:$mux t:$pmux"); + int mux_count = 0; int pmux_count = 0; for (auto module : design->selected_modules()) { - MuxpackWorker worker(module, ignore_excl); + MuxpackWorker worker(module, assume_excl); mux_count += worker.mux_count; pmux_count += worker.pmux_count; } diff --git a/passes/opt/opt_balance_tree.cc b/passes/opt/opt_balance_tree.cc index 2edd5d5d9..90f574f87 100644 --- a/passes/opt/opt_balance_tree.cc +++ b/passes/opt/opt_balance_tree.cc @@ -27,13 +27,17 @@ PRIVATE_NAMESPACE_BEGIN struct OptBalanceTreeWorker { + // Module and signal map Module *module; SigMap sigmap; + // Counts of each cell type that are getting balanced dict cell_count; + // Cells to remove pool remove_cells; + // Signal chain data structures dict sig_chain_next; dict sig_chain_prev; pool sigbit_with_non_chain_users; @@ -59,7 +63,7 @@ struct OptBalanceTreeWorker { SigSpec y_sig = sigmap(cell->getPort(ID::Y)); // If a_sig already has a chain user, mark its bits as having non-chain users - if (sig_chain_next.count(a_sig) && !a_sig.is_fully_const()) // also ok if a_sig is fully const + if (sig_chain_next.count(a_sig) && !a_sig.is_fully_const()) // ok if a_sig is fully const for (auto a_bit : a_sig.bits()) sigbit_with_non_chain_users.insert(a_bit); // Otherwise, mark cell as the next in the chain relative to a_sig @@ -70,7 +74,7 @@ struct OptBalanceTreeWorker { if (!b_sig.empty()) { // If b_sig already has a chain user, mark its bits as having non-chain users - if (sig_chain_next.count(b_sig) && !b_sig.is_fully_const()) // also ok if b_sig is fully const + if (sig_chain_next.count(b_sig) && !b_sig.is_fully_const()) // ok if b_sig is fully const for (auto b_bit : b_sig.bits()) sigbit_with_non_chain_users.insert(b_bit); // Otherwise, mark cell as the next in the chain relative to b_sig @@ -152,6 +156,8 @@ struct OptBalanceTreeWorker { Cell *mid_cell = chain[GetSize(chain) / 2]; Cell *midnext_cell = chain[GetSize(chain) / 2 + 1]; Cell *end_cell = chain.back(); + log("Balancing chain of %d cells: mid=%s, midnext=%s, endcell=%s\n", + GetSize(chain), log_id(mid_cell), log_id(midnext_cell), log_id(end_cell)); // Get mid signals SigSpec mid_a_sig = sigmap(mid_cell->getPort(ID::A)); @@ -173,10 +179,14 @@ struct OptBalanceTreeWorker { midnext_cell->unsetPort(midnext_chain_port); end_cell->unsetPort(ID::Y); + // Create new mid wire + Wire *mid_wire = module->addWire(NEW_ID, GetSize(mid_non_chain_sig)); + // Perform rotation + mid_cell->setPort(mid_non_chain_port, mid_wire); mid_cell->setPort(ID::Y, end_y_sig); midnext_cell->setPort(midnext_chain_port, mid_non_chain_sig); - end_cell->setPort(ID::Y, mid_cell->getPort(mid_non_chain_port)); + end_cell->setPort(ID::Y, mid_wire); // Recurse on subtrees vector left_chain(chain.begin(), chain.begin() + GetSize(chain) / 2); @@ -213,6 +223,7 @@ struct OptBalanceTreeWorker { for (auto c : chain_start_cells) { vector chain = create_chain(c); process_chain(chain); + cell_count[cell_type] += GetSize(chain); } // Clean up @@ -252,10 +263,8 @@ struct OptBalanceTreePass : public Pass { extra_args(args, argidx, design); // Run splitfanout pass first - if (splitfanout) { - string cmd = "splitfanout t:$and t:$or t:$xor t:$add t:$mul"; - Pass::call(design, cmd); - } + if (splitfanout) + Pass::call(design, "splitfanout t:$and t:$or t:$xor t:$add t:$mul"); // Count of all cells that were packed dict cell_count; @@ -269,7 +278,7 @@ struct OptBalanceTreePass : public Pass { // Log stats for (auto cell_type : cell_types) - log("Converted %d %s cells into %s trees.\n", cell_count[cell_type], log_id(cell_type), log_id(cell_type.str() + "_tree")); + log("Converted %d %s cells into trees.\n", cell_count[cell_type], log_id(cell_type)); } } OptBalanceTreePass; diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 74813bca9..6e1d9cd35 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -7,6 +7,9 @@ OBJS += passes/techmap/maccmap.o OBJS += passes/techmap/booth.o OBJS += passes/techmap/libparse.o +OBJS += passes/techmap/bmuxmap.o +OBJS += passes/techmap/demuxmap.o + ifeq ($(ENABLE_ABC),1) OBJS += passes/techmap/abc.o OBJS += passes/techmap/abc9.o @@ -30,8 +33,6 @@ OBJS += passes/techmap/extract_reduce.o OBJS += passes/techmap/alumacc.o OBJS += passes/techmap/dffinit.o OBJS += passes/techmap/pmuxtree.o -OBJS += passes/techmap/bmuxmap.o -OBJS += passes/techmap/demuxmap.o OBJS += passes/techmap/bwmuxmap.o OBJS += passes/techmap/muxcover.o OBJS += passes/techmap/aigmap.o