diff --git a/kernel/cost.cc b/kernel/cost.cc index d7641c26735..20079d4ff97 100644 --- a/kernel/cost.cc +++ b/kernel/cost.cc @@ -90,6 +90,7 @@ static unsigned int max_inp_coef(RTLIL::IdString type) // clang-format on return 0; } + static unsigned int sum_coef(RTLIL::IdString type) { // clang-format off @@ -106,6 +107,11 @@ static unsigned int sum_coef(RTLIL::IdString type) return 0; } +static unsigned int is_div_mod(RTLIL::IdString type) +{ + return (type == ID($div) || type == ID($divfloor) || type == ID($mod) || type == ID($modfloor)); +} + static bool is_free(RTLIL::IdString type) { // clang-format off @@ -142,6 +148,36 @@ static bool is_free(RTLIL::IdString type) // clang-format on } +unsigned int max_inp_width(RTLIL::Cell *cell) +{ + unsigned int max = 0; + RTLIL::IdString input_width_params[] = { + ID::WIDTH, + ID::A_WIDTH, + ID::B_WIDTH, + ID::S_WIDTH, + }; + + for (RTLIL::IdString param : input_width_params) + if (cell->hasParam(param)) + max = std::max(max, (unsigned int)cell->getParam(param).as_int()); + return max; +} + +unsigned int port_width_sum(RTLIL::Cell *cell) +{ + unsigned int sum = 0; + RTLIL::IdString port_width_params[] = { + ID::WIDTH, ID::A_WIDTH, ID::B_WIDTH, ID::S_WIDTH, ID::Y_WIDTH, + }; + + for (auto param : port_width_params) + if (cell->hasParam(param)) + sum += cell->getParam(param).as_int(); + + return sum; +} + unsigned int CellCosts::get(RTLIL::Cell *cell) { @@ -164,33 +200,19 @@ unsigned int CellCosts::get(RTLIL::Cell *cell) return width * y_coef(cell->type); } else if (sum_coef(cell->type)) { // linear with sum of port widths - unsigned int sum = 0; - RTLIL::IdString port_width_params[] = { - ID::WIDTH, ID::A_WIDTH, ID::B_WIDTH, ID::S_WIDTH, ID::Y_WIDTH, - }; - - for (auto param : port_width_params) - if (cell->hasParam(param)) - sum += cell->getParam(param).as_int(); - + unsigned int sum = port_width_sum(cell); log_debug("%s sum*coef %d * %d\n", cell->name.c_str(), sum, sum_coef(cell->type)); return sum * sum_coef(cell->type); } else if (max_inp_coef(cell->type)) { // linear with largest input width - unsigned int max = 0; - RTLIL::IdString input_width_params[] = { - ID::WIDTH, - ID::A_WIDTH, - ID::B_WIDTH, - ID::S_WIDTH, - }; - - for (RTLIL::IdString param : input_width_params) - if (cell->hasParam(param)) - max = std::max(max, (unsigned int)cell->getParam(param).as_int()); - + unsigned int max = max_inp_width(cell); log_debug("%s max*coef %d * %d\n", cell->name.c_str(), max, max_inp_coef(cell->type)); - return max; + return max * max_inp_coef(cell->type); + } else if (is_div_mod(cell->type)) { + // quadratic with sum of port widths + int sum = port_width_sum(cell); + log_debug("%s coef*(sum**2) 5 * %d\n", cell->name.c_str(), sum * sum); + return 5 * sum * sum; } else if (is_free(cell->type)) { log_debug("%s is free\n", cell->name.c_str()); return 0;