diff --git a/docs/source/code_examples/macro_commands/opt.ys b/docs/source/code_examples/macro_commands/opt.ys index fe2a05f4d39..5ed6aba0ebf 100644 --- a/docs/source/code_examples/macro_commands/opt.ys +++ b/docs/source/code_examples/macro_commands/opt.ys @@ -13,4 +13,4 @@ do opt_boundary (-boundary only) opt_clean opt_expr -while +while (up to -max_iter iterations) diff --git a/passes/opt/opt.cc b/passes/opt/opt.cc index 9fc1e9490c9..e7e830aefaa 100644 --- a/passes/opt/opt.cc +++ b/passes/opt/opt.cc @@ -50,7 +50,7 @@ struct OptPass : public Pass { log(" opt_boundary (-boundary only)\n"); log(" opt_clean [-purge]\n"); log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-noclkinv] [-fine] [-full] [-keepdc]\n"); - log(" while \n"); + log(" while (up to -max_iter iterations)\n"); log("\n"); log("When called with -fast the following script is used instead:\n"); log("\n"); @@ -61,11 +61,14 @@ struct OptPass : public Pass { log(" opt_hier (-hier only)\n"); log(" opt_boundary (-boundary only)\n"); log(" opt_clean [-purge]\n"); - log(" while \n"); + log(" while (up to -max_iter iterations)\n"); log("\n"); log("Note: Options in square brackets (such as [-keepdc]) are passed through to\n"); log("the opt_* commands when given to 'opt'.\n"); log("\n"); + log(" -max_iter \n"); + log(" only run the specified number of iterations.\n"); + log(" default: 20. use 0 for unlimited.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) override @@ -80,6 +83,8 @@ struct OptPass : public Pass { bool noff_mode = false; bool hier_mode = false; bool boundary_mode = false; + int max_iter = 20; + bool reached_max_iter = false; log_header(design, "Executing OPT pass (performing simple optimizations).\n"); log_push(); @@ -155,13 +160,19 @@ struct OptPass : public Pass { boundary_mode = true; continue; } + if (args[argidx] == "-max_iter" && argidx+1 < args.size()) { + max_iter = atoi(args[++argidx].c_str()); + continue; + } break; } extra_args(args, argidx, design); if (fast_mode) { + int iter = 0; while (1) { + iter++; Pass::call(design, "opt_expr" + opt_expr_args); Pass::call(design, "opt_merge" + opt_merge_args); design->scratchpad_unset("opt.did_something"); @@ -174,6 +185,10 @@ struct OptPass : public Pass { if (boundary_mode) Pass::call(design, "opt_boundary"); Pass::call(design, "opt_clean" + opt_clean_args); + if (max_iter > 0 && iter >= max_iter) { + reached_max_iter = true; + break; + } log_header(design, "Rerunning OPT passes. (Removed registers in this run.)\n"); } Pass::call(design, "opt_clean" + opt_clean_args); @@ -182,7 +197,9 @@ struct OptPass : public Pass { { Pass::call(design, "opt_expr" + opt_expr_args); Pass::call(design, "opt_merge -nomux" + opt_merge_args); + int iter = 0; while (1) { + iter++; design->scratchpad_unset("opt.did_something"); Pass::call(design, "opt_muxtree"); Pass::call(design, "opt_reduce" + opt_reduce_args); @@ -199,6 +216,10 @@ struct OptPass : public Pass { Pass::call(design, "opt_expr" + opt_expr_args); if (design->scratchpad_get_bool("opt.did_something") == false) break; + if (max_iter > 0 && iter >= max_iter) { + reached_max_iter = true; + break; + } log_header(design, "Rerunning OPT passes. (Maybe there is more to do..)\n"); } } @@ -207,7 +228,9 @@ struct OptPass : public Pass { design->sort(); design->check(); - log_header(design, "Finished fast OPT passes.%s\n", fast_mode ? "" : " (There is nothing left to do.)"); + const char *done_reason = reached_max_iter ? " (Reached maximum number of iterations.)" : + (fast_mode ? "" : " (There is nothing left to do.)"); + log_header(design, "Finished %sOPT passes.%s\n", fast_mode ? "fast " : "", done_reason); log_pop(); } } OptPass;