diff --git a/passes/cmds/splitfanout.cc b/passes/cmds/splitfanout.cc index 2a7f5ad04..69c92b7cb 100644 --- a/passes/cmds/splitfanout.cc +++ b/passes/cmds/splitfanout.cc @@ -67,7 +67,7 @@ struct SplitfanoutWorker } } - int split(Cell *cell) + int split(Cell *cell, int fanoutlimit) { // Get output signal/port SigSpec outsig; @@ -93,8 +93,8 @@ struct SplitfanoutWorker } } - // Skip if output signal has only one user - if (GetSize(bit_users) <= 1) + // Skip if output signal has only one user or too many users + if (GetSize(bit_users) <= 1 || GetSize(bit_users) > fanoutlimit) return 0; // Iterate over bit users and create a new cell for each one @@ -148,7 +148,7 @@ struct SplitfanoutPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" splitfanout [selection]\n"); + log(" splitfanout [options] [selection]\n"); log("\n"); log("This command copies selected cells with >1 fanout into cells with fanout 1. It\n"); log("is effectively the opposite of the opt_merge pass.\n"); @@ -156,16 +156,23 @@ struct SplitfanoutPass : public Pass { log("This command operates only on cells with 1 output and no \"bit split\" on that\n"); log("output.\n"); log("\n"); + log(" -fanoutlimit\n"); + log(" fanout limit for splitfanout, beyond which no split (default: 10)\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) override { + int fanoutlimit = 10; + log_header(design, "Executing SPLITFANOUT pass (splitting up cells with >1 fanout into copies).\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - // No options currently. When adding in the future make sure to update docstring with [options] - break; + if ((args[argidx] == "-fanoutlimit") && ((argidx + 1) < args.size())) { + fanoutlimit = std::stoi(args[++argidx]); + continue; + } } extra_args(args, argidx, design); @@ -178,7 +185,7 @@ struct SplitfanoutPass : public Pass { SplitfanoutWorker worker(module); bool did_something = false; for (auto cell : module->selected_cells()) { - int n = worker.split(cell); + int n = worker.split(cell, fanoutlimit); did_something |= (n != 0); count_split_pre += (n != 0); count_split_post += n; diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 3f7ee7221..fd8fcd3c4 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -344,6 +344,9 @@ struct MuxpackPass : public Pass { log(" -splitfanout\n"); log(" run splitfanout pass first\n"); log("\n"); + log(" -fanoutlimit\n"); + log(" fanout limit for splitfanout, beyond which no split (default: 10)\n"); + log("\n"); log(" -assume_excl\n"); log(" assume mutually exclusive constraint when packing (may result in inequivalence)\n"); log("\n"); @@ -352,6 +355,7 @@ struct MuxpackPass : public Pass { { bool splitfanout = false; bool assume_excl = false; + int fanoutlimit = 10; log_header(design, "Executing MUXPACK pass ($mux cell cascades to $pmux).\n"); @@ -362,6 +366,10 @@ struct MuxpackPass : public Pass { splitfanout = true; continue; } + if ((args[argidx] == "-fanoutlimit") && ((argidx + 1) < args.size())) { + fanoutlimit = std::stoi(args[++argidx]); + continue; + } if (args[argidx] == "-assume_excl") { assume_excl = true; continue; @@ -371,7 +379,7 @@ struct MuxpackPass : public Pass { extra_args(args, argidx, design); if (splitfanout) - Pass::call(design, "splitfanout t:$mux t:$pmux"); + Pass::call(design, stringf("splitfanout -fanoutlimit %d t:$mux t:$pmux", fanoutlimit)); int mux_count = 0; int pmux_count = 0; diff --git a/passes/opt/opt_balance_tree.cc b/passes/opt/opt_balance_tree.cc index fc48974df..c608c280a 100644 --- a/passes/opt/opt_balance_tree.cc +++ b/passes/opt/opt_balance_tree.cc @@ -314,9 +314,13 @@ struct OptBalanceTreePass : public Pass { log(" -splitfanout\n"); log(" run splitfanout pass first\n"); log("\n"); + log(" -fanoutlimit\n"); + log(" fanout limit for splitfanout, beyond which no split (default: 10)\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) override { bool splitfanout = false; + int fanoutlimit = 10; log_header(design, "Executing OPT_BALANCE_TREE pass (cell cascades to trees).\n"); @@ -327,13 +331,17 @@ struct OptBalanceTreePass : public Pass { splitfanout = true; continue; } + if ((args[argidx] == "-fanoutlimit") && ((argidx + 1) < args.size())) { + fanoutlimit = std::stoi(args[++argidx]); + continue; + } break; } extra_args(args, argidx, design); // Run splitfanout pass first if (splitfanout) - Pass::call(design, "splitfanout t:$and t:$or t:$xor t:$add t:$mul"); + Pass::call(design, stringf("splitfanout -fanoutlimit %d t:$and t:$or t:$xor t:$add t:$mul", fanoutlimit)); // Count of all cells that were packed dict cell_count;