mirror of https://github.com/YosysHQ/yosys.git
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.
This commit is contained in:
parent
62bff3a204
commit
2f0f10cb87
|
@ -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<std::string> 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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue