From 2f0f10cb871228248c8e012a9d6756c1e1b972c1 Mon Sep 17 00:00:00 2001 From: Philippe Sauter Date: Fri, 14 Jun 2024 15:30:03 +0200 Subject: [PATCH] peepopt: limit padding from shiftadd The input to a shift operation is padded. This reduced the final number of MUX cells but during techmap it can create huge temporary multiplexers in the log shifter. This significantly increases runtime and resources. A limit is added with a warning when it is used. --- passes/pmgen/peepopt.cc | 11 +++++++++++ passes/pmgen/peepopt_shiftadd.pmg | 15 ++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/peepopt.cc b/passes/pmgen/peepopt.cc index edd3b18a8..5638ec3c2 100644 --- a/passes/pmgen/peepopt.cc +++ b/passes/pmgen/peepopt.cc @@ -25,6 +25,9 @@ PRIVATE_NAMESPACE_BEGIN bool did_something; +// scratchpad configurations for pmgen +int shiftadd_max_ratio; + #include "passes/pmgen/peepopt_pm.h" struct PeepoptPass : public Pass { @@ -50,6 +53,9 @@ struct PeepoptPass : public Pass { log("\n"); log(" * shiftadd - Replace A>>(B+D) with (A'>>D)>>(B) where D is constant and\n"); log(" A' is derived from A by padding or cutting inaccessible bits.\n"); + log(" Scratchpad: 'peepopt.shiftadd.max_data_multiple' (default: 2)\n"); + log(" limits the amount of padding to a multiple of the data, \n"); + log(" to avoid high resource usage from large temporary MUX trees.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) override @@ -63,6 +69,11 @@ struct PeepoptPass : public Pass { } extra_args(args, argidx, design); + // limit the padding from shiftadd to a multiple of the input data + // during techmap it creates (#data + #padding) * log(shift) $_MUX_ cells + // 2x implies there is a constant shift larger than the input-data which should be extremely rare + shiftadd_max_ratio = design->scratchpad_get_int("peepopt.shiftadd.max_data_multiple", 2); + for (auto module : design->selected_modules()) { did_something = true; diff --git a/passes/pmgen/peepopt_shiftadd.pmg b/passes/pmgen/peepopt_shiftadd.pmg index e690ff651..62f54efe5 100644 --- a/passes/pmgen/peepopt_shiftadd.pmg +++ b/passes/pmgen/peepopt_shiftadd.pmg @@ -91,11 +91,21 @@ code // it should only differ if previous passes create invalid data log_assert(!(offset>0 && var_signed)); + SigSpec old_a = port(shift, \A); // data + std::string location = shift->get_src_attribute(); + + if(shiftadd_max_ratio>0 && offset<0 && -offset*shiftadd_max_ratio > old_a.size()) { + log_warning("at %s: candiate for shiftadd optimization (shifting '%s' by '%s - %d' bits) " + "was ignored to avoid high resource usage, see help peepopt\n", + location.c_str(), log_signal(old_a), log_signal(var_signal), -offset); + reject; + } + did_something = true; log("shiftadd pattern in %s: shift=%s, add/sub=%s, offset: %d\n", \ log_id(module), log_id(shift), log_id(add), offset); - SigSpec old_a = port(shift, \A), new_a; + SigSpec new_a; if(offset<0) { // data >> (...-c) transformed to {data, c'X} >> (...) SigSpec padding( (shift->type.in($shiftx) ? State::Sx : State::S0), -offset ); @@ -107,14 +117,13 @@ code new_a.append(old_a.extract_end(offset)); } else { // warn user in case data is empty (no bits left) - std::string location = shift->get_src_attribute(); if (location.empty()) location = shift->name.str(); if(shift->type.in($shiftx)) log_warning("at %s: result of indexed part-selection is always constant (selecting from '%s' with index '%s + %d')\n", \ location.c_str(), log_signal(old_a), log_signal(var_signal), offset); else - log_warning("at %s: result of shift operation is always constant (shifting '%s' by '%s + %d'-bits)\n", \ + log_warning("at %s: result of shift operation is always constant (shifting '%s' by '%s + %d' bits)\n", \ location.c_str(), log_signal(old_a), log_signal(var_signal), offset); } }