From 2c930d2c35679e167d64ee35ac254adce37ec0f1 Mon Sep 17 00:00:00 2001 From: Emil Tywoniak Date: Wed, 17 Apr 2024 20:37:55 +0200 Subject: [PATCH] cost: fix --- kernel/cost.cc | 176 +++++++++++++++++++------------------- passes/techmap/flatten.cc | 17 ++-- 2 files changed, 101 insertions(+), 92 deletions(-) diff --git a/kernel/cost.cc b/kernel/cost.cc index 2aacbf76158..2cffdc2b338 100644 --- a/kernel/cost.cc +++ b/kernel/cost.cc @@ -4,9 +4,6 @@ USING_YOSYS_NAMESPACE int CellCosts::get(RTLIL::Module *mod) { - if (mod->attributes.count(ID(cost))) - return mod->attributes.at(ID(cost)).as_int(); - if (mod_cost_cache_.count(mod->name)) return mod_cost_cache_.at(mod->name); @@ -22,34 +19,34 @@ static int y_coef(RTLIL::IdString type) { // clang-format off if (// equality - type == ID('$bweqx') || - type == ID('$nex') || - type == ID('$eqx') || + type == ID($bweqx) || + type == ID($nex) || + type == ID($eqx) || // basic logic - type == ID('$and') || - type == ID('$or') || - type == ID('$xor') || - type == ID('$xnor') || - type == ID('$not') || + type == ID($and) || + type == ID($or) || + type == ID($xor) || + type == ID($xnor) || + type == ID($not) || // mux - type == ID('$bwmux') || - type == ID('$mux') || - type == ID('$demux') || + type == ID($bwmux) || + type == ID($mux) || + type == ID($demux) || // others - type == ID('$tribuf')) { + type == ID($tribuf)) { return 1; - } else if (type == ID('$neg')) { + } else if (type == ID($neg)) { return 4; - } else if (type == ID('$fa')) { + } else if (type == ID($fa)) { return 5; } else if (// multi-bit adders - type == ID('$add') || - type == ID('$sub') || - type == ID('$alu')) { + type == ID($add) || + type == ID($sub) || + type == ID($alu)) { return 8; } else if (// left shift - type == ID('$shl') || - type == ID('$sshl')) { + type == ID($shl) || + type == ID($sshl)) { return 10; } // clang-format on @@ -60,31 +57,32 @@ static int max_inp_coef(RTLIL::IdString type) { // clang-format off if (// binop reduce - type == ID('$reduce_and') || - type == ID('$reduce_or') || - type == ID('$reduce_xor') || - type == ID('$reduce_xnor') || - type == ID('$reduce_bool') || + type == ID($reduce_and) || + type == ID($reduce_or) || + type == ID($reduce_xor) || + type == ID($reduce_xnor) || + type == ID($reduce_bool) || // others - type == ID('$logic_not') || - type == ID('$bmux')) { + type == ID($logic_not) || + type == ID($pmux) || + type == ID($bmux)) { return 1; } else if (// equality - type == ID('$eq') || - type == ID('$ne') || + type == ID($eq) || + type == ID($ne) || // logic - type == ID('$logic_and') || - type == ID('$logic_or')) { + type == ID($logic_and) || + type == ID($logic_or)) { return 2; - } else if (type == ID('$lcu')) { + } else if (type == ID($lcu)) { return 5; } else if (// comparison - type == ID('$lt') || - type == ID('$le') || - type == ID('$ge') || - type == ID('$gt') || + type == ID($lt) || + type == ID($le) || + type == ID($ge) || + type == ID($gt) || // others - type == ID('$sop')) { + type == ID($sop)) { return 6; } // clang-format on @@ -94,16 +92,15 @@ static int sum_coef(RTLIL::IdString type) { // clang-format off if (// right shift - type == ID('$shr') || - type == ID('$sshr')) { + type == ID($shr) || + type == ID($sshr)) { return 4; } else if (// shift - type == ID('$shift') || - type == ID('$shiftx')) { + type == ID($shift) || + type == ID($shiftx)) { return 8; } - // clang-format on - + // clang-format on return 0; } @@ -111,51 +108,38 @@ static bool is_free(RTLIL::IdString type) { // clang-format off return (// tags - type == ID('$overwrite_tag') || - type == ID('$set_tag') || - type == ID('$original_tag') || - type == ID('$get_tag') || + type == ID($overwrite_tag) || + type == ID($set_tag) || + type == ID($original_tag) || + type == ID($get_tag) || // formal - type == ID('$check') || - type == ID('$equiv') || - type == ID('$initstate') || - type == ID('$assert') || - type == ID('$assume') || - type == ID('$live') || - type == ID('$cover') || - type == ID('$allseq') || - type == ID('$allconst') || - type == ID('$anyseq') || - type == ID('$anyinit') || - type == ID('$anyconst') || - type == ID('$fair') || + type == ID($check) || + type == ID($equiv) || + type == ID($initstate) || + type == ID($assert) || + type == ID($assume) || + type == ID($live) || + type == ID($cover) || + type == ID($allseq) || + type == ID($allconst) || + type == ID($anyseq) || + type == ID($anyinit) || + type == ID($anyconst) || + type == ID($fair) || // utilities - type == ID('$scopeinfo') || - type == ID('$print') || + type == ID($scopeinfo) || + type == ID($print) || // real but free - type == ID('$concat') || - type == ID('$slice') || - type == ID('$pos') || + type == ID($concat) || + type == ID($slice) || + type == ID($pos) || // specify - type == ID('$specrule') || - type == ID('$specify2') || - type == ID('$specify3')); + type == ID($specrule) || + type == ID($specify2) || + type == ID($specify3)); // clang-format on } -static const RTLIL::IdString port_width_params[] = { - ID::WIDTH, ID::A_WIDTH, ID::B_WIDTH, ID::S_WIDTH, ID::Y_WIDTH, -}; - -// Ditto but without Y_WIDTH -// No neat solution available: https://stackoverflow.com/questions/3154170/combine-two-constant-strings-or-arrays-into-one-constant-string-or-array-at -static const RTLIL::IdString input_width_params[] = { - ID::WIDTH, - ID::A_WIDTH, - ID::B_WIDTH, - ID::S_WIDTH, -}; - int CellCosts::get(RTLIL::Cell *cell) { @@ -163,32 +147,50 @@ int CellCosts::get(RTLIL::Cell *cell) return gate_type_cost().at(cell->type); if (design_ && design_->module(cell->type) && cell->parameters.empty()) { + log_debug("%s is a module, recurse\n", cell->name.c_str()); return get(design_->module(cell->type)); } else if (RTLIL::builtin_ff_cell_types().count(cell->type)) { log_assert(cell->hasPort(ID::Q) && "Weird flip flop"); + log_debug("%s is ff\n", cell->name.c_str()); return cell->getParam(ID::WIDTH).as_int(); } else if (y_coef(cell->type)) { - // linear with Y_WIDTH - log_assert(cell->hasParam(ID::Y_WIDTH) && "No Y port"); - int width = cell->getParam(ID::Y_WIDTH).as_int(); + // linear with Y_WIDTH or WIDTH + log_assert((cell->hasParam(ID::Y_WIDTH) || cell->hasParam(ID::WIDTH)) && "Unknown width"); + auto param = cell->hasParam(ID::Y_WIDTH) ? ID::Y_WIDTH : ID::WIDTH; + int width = cell->getParam(param).as_int(); + log_debug("%s Y*coef %d * %d\n", cell->name.c_str(), width, y_coef(cell->type)); return width * y_coef(cell->type); } else if (sum_coef(cell->type)) { // linear with sum of port widths 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(); + 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 int max = 0; - for (auto param : input_width_params) + 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, cell->getParam(param).as_int()); + log_debug("%s max*coef %d * %d\n", cell->name.c_str(), max, max_inp_coef(cell->type)); return max; } else if (is_free(cell->type)) { + log_debug("%s is free\n", cell->name.c_str()); return 0; } // TODO: $fsm $mem.* diff --git a/passes/techmap/flatten.cc b/passes/techmap/flatten.cc index fee9370487d..7a95a244e86 100644 --- a/passes/techmap/flatten.cc +++ b/passes/techmap/flatten.cc @@ -20,6 +20,7 @@ #include "kernel/yosys.h" #include "kernel/utils.h" #include "kernel/sigtools.h" +#include "kernel/cost.h" #include #include @@ -60,6 +61,8 @@ struct FlattenWorker bool ignore_wb = false; bool create_scopeinfo = true; bool create_scopename = false; + CellCosts costs; + FlattenWorker(RTLIL::Design *design) : costs(CellCosts(CellCosts::DEFAULT, design)) { } int max_cost = INT_MAX; template @@ -305,10 +308,14 @@ struct FlattenWorker continue; } - if (tpl->has_attribute(ID::cost) && tpl->attributes[ID::cost].as_int() > max_cost) { - log("Keeping %s.%s (module too big).\n", log_id(module), log_id(cell)); - used_modules.insert(tpl); - continue; + // Deliberate short circuit + if (max_cost != INT_MAX) { + int cost = costs.get(cell); + if (cost > max_cost) { + log("Keeping %s.%s (module too big: %d > %d).\n", log_id(module), log_id(cell), cost, max_cost); + used_modules.insert(tpl); + continue; + } } log_debug("Flattening %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); @@ -358,7 +365,7 @@ struct FlattenPass : public Pass { log_header(design, "Executing FLATTEN pass (flatten design).\n"); log_push(); - FlattenWorker worker; + FlattenWorker worker(design); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) {