diff --git a/Makefile b/Makefile index f8d628010c5..5306c8498cc 100644 --- a/Makefile +++ b/Makefile @@ -646,7 +646,7 @@ $(eval $(call add_include_file,backends/rtlil/rtlil_backend.h)) OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o OBJS += kernel/binding.o -OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o +OBJS += kernel/cellaigs.o kernel/celledges.o kernel/cost.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o ifeq ($(ENABLE_ZLIB),1) OBJS += kernel/fstdata.o endif diff --git a/kernel/cost.cc b/kernel/cost.cc index 40986a52bb6..fd4f15a2b52 100644 --- a/kernel/cost.cc +++ b/kernel/cost.cc @@ -2,7 +2,117 @@ USING_YOSYS_NAMESPACE -CellCosts::CellCosts(CellCosts::CostKind kind, RTLIL::Design *design) : kind(kind), design(design) { +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); + + int module_cost = 1; + for (auto c : mod->cells()) + module_cost += get(c); + + mod_cost_cache_[mod->name] = module_cost; + return module_cost; +} + +static int y_coef(RTLIL::IdString type) +{ + if (type == ID('$bweqx') || + type == ID('$nex') || + type == ID('$eqx') || + type == ID('$and') || + type == ID('$or') || + type == ID('$xor') || + type == ID('$xnor') || + type == ID('$not')) + return 1; + else if ( + type == ID('$neg') + ) + return 3; + return 0; +} + +static int sum_coef(RTLIL::IdString type) +{ + if (type == ID('$reduce_and') || + type == ID('$reduce_or') || + type == ID('$reduce_xor') || + type == ID('$reduce_xnor') || + type == ID('$reduce_bool')) + return 1; + + return 0; +} + +int CellCosts::get(RTLIL::Cell *cell) +{ + if (gate_type_cost().count(cell->type)) + return gate_type_cost().at(cell->type); + + if (design_ && design_->module(cell->type) && cell->parameters.empty()) + { + 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"); + 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(); + return width * y_coef(cell->type); + } else if (sum_coef(cell->type)) { + // linear with sum of port widths + int sum = 0; + + if (cell->hasParam(ID::A_WIDTH)) + sum += cell->getParam(ID::A_WIDTH).as_int(); + if (cell->hasParam(ID::B_WIDTH)) + sum += cell->getParam(ID::B_WIDTH).as_int(); + if (cell->hasParam(ID::S_WIDTH)) + sum += cell->getParam(ID::S_WIDTH).as_int(); + if (cell->hasParam(ID::Y_WIDTH)) + sum += cell->getParam(ID::Y_WIDTH).as_int(); + if (cell->hasParam(ID::WIDTH)) + sum += cell->getParam(ID::WIDTH).as_int(); + + + // TODO CTRL_IN $fsm ? + // TODO CTRL_OUT $fsm ? + + return sum * sum_coef(cell->type); + } else if ( + cell->type == ID('$overwrite_tag') || + cell->type == ID('$set_tag') || + cell->type == ID('$original_tag') || + cell->type == ID('$get_tag') || + cell->type == ID('$check') || + cell->type == ID('$equiv') || + cell->type == ID('$initstate') || + cell->type == ID('$assert') || + cell->type == ID('$assume') || + cell->type == ID('$live') || + cell->type == ID('$cover') || + cell->type == ID('$allseq') || + cell->type == ID('$allconst') || + cell->type == ID('$anyseq') || + cell->type == ID('$anyinit') || + cell->type == ID('$anyconst') || + cell->type == ID('$fair') || + cell->type == ID('$scopeinfo') || + cell->type == ID('$print') || + cell->type == ID('$concat') || + cell->type == ID('$slice') || + cell->type == ID('$pos') + ) { + return 0; + } + + log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(cell->type), GetSize(cell->parameters)); + return 1; } diff --git a/kernel/cost.h b/kernel/cost.h index ec8c4bec5ab..b8916f0f323 100644 --- a/kernel/cost.h +++ b/kernel/cost.h @@ -33,13 +33,12 @@ struct CellCosts }; private: - dict mod_cost_cache; - CostKind kind; - Design *design = nullptr; - bool type_only; + dict mod_cost_cache_; + CostKind kind_; + Design *design_ = nullptr; public: - CellCosts(CostKind kind, Design *design); + CellCosts(CellCosts::CostKind kind, RTLIL::Design *design) : kind_(kind), design_(design) { } const dict& gate_type_cost() { static const dict default_gate_db = { @@ -83,7 +82,7 @@ struct CellCosts { ID($_DFF_P_), 16 }, { ID($_DFF_N_), 16 }, }; - switch (kind) { + switch (kind_) { case DEFAULT: return default_gate_db; case CMOS: @@ -93,38 +92,8 @@ struct CellCosts } } - int 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); - - int module_cost = 1; - for (auto c : mod->cells()) - module_cost += get(c); - - mod_cost_cache[mod->name] = module_cost; - return module_cost; - } - - int get(RTLIL::Cell *cell) - { - if (gate_type_cost().count(cell->type)) - return gate_type_cost().at(cell->type); - - if (design && design->module(cell->type) && cell->parameters.empty()) - { - 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"); - return cell->getParam(ID::WIDTH).as_int(); - } - - log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(cell->type), GetSize(cell->parameters)); - return 1; - } + int get(RTLIL::Module *mod); + int get(RTLIL::Cell *cell); }; YOSYS_NAMESPACE_END