YOSYS_NAMESPACE_BEGIN
-int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr, bool cmos_cost = false);
-
-inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL::Const> ¶meters = dict<RTLIL::IdString, RTLIL::Const>(),
- RTLIL::Design *design = nullptr, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr, bool cmos_cost = false)
+struct CellCosts
{
- static dict<RTLIL::IdString, int> gate_cost = {
- { "$_BUF_", 1 },
- { "$_NOT_", 2 },
- { "$_AND_", 4 },
- { "$_NAND_", 4 },
- { "$_OR_", 4 },
- { "$_NOR_", 4 },
- { "$_ANDNOT_", 4 },
- { "$_ORNOT_", 4 },
- { "$_XOR_", 8 },
- { "$_XNOR_", 8 },
- { "$_AOI3_", 6 },
- { "$_OAI3_", 6 },
- { "$_AOI4_", 8 },
- { "$_OAI4_", 8 },
- { "$_MUX_", 4 },
- { "$_NMUX_", 4 }
- };
-
- // match costs in "stat -tech cmos"
- static dict<RTLIL::IdString, int> cmos_gate_cost = {
- { "$_BUF_", 1 },
- { "$_NOT_", 2 },
- { "$_AND_", 6 },
- { "$_NAND_", 4 },
- { "$_OR_", 6 },
- { "$_NOR_", 4 },
- { "$_ANDNOT_", 6 },
- { "$_ORNOT_", 6 },
- { "$_XOR_", 12 },
- { "$_XNOR_", 12 },
- { "$_AOI3_", 6 },
- { "$_OAI3_", 6 },
- { "$_AOI4_", 8 },
- { "$_OAI4_", 8 },
- { "$_MUX_", 12 },
- { "$_NMUX_", 10 }
- };
-
- if (cmos_cost && cmos_gate_cost.count(type))
- return cmos_gate_cost.at(type);
-
- if (gate_cost.count(type))
- return gate_cost.at(type);
-
- if (parameters.empty() && design && design->module(type))
+ static const dict<RTLIL::IdString, int>& default_gate_cost() {
+ static const dict<RTLIL::IdString, int> db = {
+ { "$_BUF_", 1 },
+ { "$_NOT_", 2 },
+ { "$_AND_", 4 },
+ { "$_NAND_", 4 },
+ { "$_OR_", 4 },
+ { "$_NOR_", 4 },
+ { "$_ANDNOT_", 4 },
+ { "$_ORNOT_", 4 },
+ { "$_XOR_", 6 },
+ { "$_XNOR_", 6 },
+ { "$_AOI3_", 6 },
+ { "$_OAI3_", 6 },
+ { "$_AOI4_", 8 },
+ { "$_OAI4_", 8 },
+ { "$_MUX_", 4 },
+ { "$_NMUX_", 4 }
+ };
+ return db;
+ }
+
+ static const dict<RTLIL::IdString, int>& cmos_gate_cost() {
+ static const dict<RTLIL::IdString, int> db = {
+ { "$_BUF_", 1 },
+ { "$_NOT_", 2 },
+ { "$_AND_", 6 },
+ { "$_NAND_", 4 },
+ { "$_OR_", 6 },
+ { "$_NOR_", 4 },
+ { "$_ANDNOT_", 6 },
+ { "$_ORNOT_", 6 },
+ { "$_XOR_", 12 },
+ { "$_XNOR_", 12 },
+ { "$_AOI3_", 6 },
+ { "$_OAI3_", 6 },
+ { "$_AOI4_", 8 },
+ { "$_OAI4_", 8 },
+ { "$_MUX_", 12 },
+ { "$_NMUX_", 10 }
+ };
+ return db;
+ }
+
+ dict<RTLIL::IdString, int> mod_cost_cache;
+ const dict<RTLIL::IdString, int> *gate_cost = nullptr;
+ Design *design = nullptr;
+
+ int get(RTLIL::IdString type) const
{
- RTLIL::Module *mod = design->module(type);
+ if (gate_cost && gate_cost->count(type))
+ return gate_cost->at(type);
- if (mod->attributes.count("\\cost"))
- return mod->attributes.at("\\cost").as_int();
+ log_warning("Can't determine cost of %s cell.\n", log_id(type));
+ return 1;
+ }
- dict<RTLIL::IdString, int> local_mod_cost_cache;
- if (mod_cost_cache == nullptr)
- mod_cost_cache = &local_mod_cost_cache;
+ int get(RTLIL::Cell *cell)
+ {
+ if (gate_cost && gate_cost->count(cell->type))
+ return gate_cost->at(cell->type);
- if (mod_cost_cache->count(mod->name))
- return mod_cost_cache->at(mod->name);
+ if (design && design->module(cell->type) && cell->parameters.empty())
+ {
+ RTLIL::Module *mod = design->module(cell->type);
- int module_cost = 1;
- for (auto c : mod->cells())
- module_cost += get_cell_cost(c, mod_cost_cache);
+ if (mod->attributes.count("\\cost"))
+ return mod->attributes.at("\\cost").as_int();
- (*mod_cost_cache)[mod->name] = module_cost;
- return module_cost;
- }
+ if (mod_cost_cache.count(mod->name))
+ return mod_cost_cache.at(mod->name);
- log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(type), GetSize(parameters));
- return 1;
-}
+ int module_cost = 1;
+ for (auto c : mod->cells())
+ module_cost += get(c);
-inline int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache, bool cmos_cost)
-{
- return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache, cmos_cost);
-}
+ mod_cost_cache[mod->name] = module_cost;
+ return module_cost;
+ }
+
+ log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(cell->type), GetSize(cell->parameters));
+ return 1;
+ }
+};
YOSYS_NAMESPACE_END
{
log_header(design, "Executing ABC.\n");
- auto cell_cost = [](IdString cell_type) {
- return get_cell_cost(cell_type, dict<RTLIL::IdString, RTLIL::Const>(), nullptr, nullptr, cmos_cost);
- };
+ auto &cell_cost = cmos_cost ? CellCosts::cmos_gate_cost() : CellCosts::default_gate_cost();
buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str());
f = fopen(buffer.c_str(), "wt");
log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
fprintf(f, "GATE ZERO 1 Y=CONST0;\n");
fprintf(f, "GATE ONE 1 Y=CONST1;\n");
- fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", cell_cost("$_BUF_"));
- fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost("$_NOT_"));
+ fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_BUF_"));
+ fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NOT_"));
if (enabled_gates.empty() || enabled_gates.count("AND"))
- fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost("$_AND_"));
+ fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_AND_"));
if (enabled_gates.empty() || enabled_gates.count("NAND"))
- fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_cost("$_NAND_"));
+ fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NAND_"));
if (enabled_gates.empty() || enabled_gates.count("OR"))
- fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost("$_OR_"));
+ fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_OR_"));
if (enabled_gates.empty() || enabled_gates.count("NOR"))
- fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_cost("$_NOR_"));
+ fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NOR_"));
if (enabled_gates.empty() || enabled_gates.count("XOR"))
- fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_XOR_"));
+ fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XOR_"));
if (enabled_gates.empty() || enabled_gates.count("XNOR"))
- fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_XNOR_"));
+ fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XNOR_"));
if (enabled_gates.empty() || enabled_gates.count("ANDNOT"))
- fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_ANDNOT_"));
+ fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ANDNOT_"));
if (enabled_gates.empty() || enabled_gates.count("ORNOT"))
- fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_ORNOT_"));
+ fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ORNOT_"));
if (enabled_gates.empty() || enabled_gates.count("AOI3"))
- fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_cost("$_AOI3_"));
+ fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_AOI3_"));
if (enabled_gates.empty() || enabled_gates.count("OAI3"))
- fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_cost("$_OAI3_"));
+ fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_OAI3_"));
if (enabled_gates.empty() || enabled_gates.count("AOI4"))
- fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", cell_cost("$_AOI4_"));
+ fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_AOI4_"));
if (enabled_gates.empty() || enabled_gates.count("OAI4"))
- fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", cell_cost("$_OAI4_"));
+ fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_OAI4_"));
if (enabled_gates.empty() || enabled_gates.count("MUX"))
- fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_MUX_"));
+ fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_MUX_"));
if (enabled_gates.empty() || enabled_gates.count("NMUX"))
- fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_NMUX_"));
+ fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_NMUX_"));
if (map_mux4)
- fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost("$_MUX_"));
+ fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost.at("$_MUX_"));
if (map_mux8)
- fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost("$_MUX_"));
+ fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost.at("$_MUX_"));
if (map_mux16)
- fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost("$_MUX_"));
+ fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost.at("$_MUX_"));
fclose(f);
if (!lut_costs.empty()) {