mirror of https://github.com/YosysHQ/yosys.git
Redesign of cell cost API
Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
parent
8110fb9266
commit
100c377451
158
kernel/cost.h
158
kernel/cost.h
|
@ -24,86 +24,92 @@
|
||||||
|
|
||||||
YOSYS_NAMESPACE_BEGIN
|
YOSYS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr, bool cmos_cost = false);
|
struct CellCosts
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
static dict<RTLIL::IdString, int> gate_cost = {
|
static const dict<RTLIL::IdString, int>& default_gate_cost() {
|
||||||
{ "$_BUF_", 1 },
|
static const dict<RTLIL::IdString, int> db = {
|
||||||
{ "$_NOT_", 2 },
|
{ "$_BUF_", 1 },
|
||||||
{ "$_AND_", 4 },
|
{ "$_NOT_", 2 },
|
||||||
{ "$_NAND_", 4 },
|
{ "$_AND_", 4 },
|
||||||
{ "$_OR_", 4 },
|
{ "$_NAND_", 4 },
|
||||||
{ "$_NOR_", 4 },
|
{ "$_OR_", 4 },
|
||||||
{ "$_ANDNOT_", 4 },
|
{ "$_NOR_", 4 },
|
||||||
{ "$_ORNOT_", 4 },
|
{ "$_ANDNOT_", 4 },
|
||||||
{ "$_XOR_", 8 },
|
{ "$_ORNOT_", 4 },
|
||||||
{ "$_XNOR_", 8 },
|
{ "$_XOR_", 6 },
|
||||||
{ "$_AOI3_", 6 },
|
{ "$_XNOR_", 6 },
|
||||||
{ "$_OAI3_", 6 },
|
{ "$_AOI3_", 6 },
|
||||||
{ "$_AOI4_", 8 },
|
{ "$_OAI3_", 6 },
|
||||||
{ "$_OAI4_", 8 },
|
{ "$_AOI4_", 8 },
|
||||||
{ "$_MUX_", 4 },
|
{ "$_OAI4_", 8 },
|
||||||
{ "$_NMUX_", 4 }
|
{ "$_MUX_", 4 },
|
||||||
};
|
{ "$_NMUX_", 4 }
|
||||||
|
};
|
||||||
// match costs in "stat -tech cmos"
|
return db;
|
||||||
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))
|
|
||||||
{
|
|
||||||
RTLIL::Module *mod = design->module(type);
|
|
||||||
|
|
||||||
if (mod->attributes.count("\\cost"))
|
|
||||||
return mod->attributes.at("\\cost").as_int();
|
|
||||||
|
|
||||||
dict<RTLIL::IdString, int> local_mod_cost_cache;
|
|
||||||
if (mod_cost_cache == nullptr)
|
|
||||||
mod_cost_cache = &local_mod_cost_cache;
|
|
||||||
|
|
||||||
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_cell_cost(c, mod_cost_cache);
|
|
||||||
|
|
||||||
(*mod_cost_cache)[mod->name] = module_cost;
|
|
||||||
return module_cost;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(type), GetSize(parameters));
|
static const dict<RTLIL::IdString, int>& cmos_gate_cost() {
|
||||||
return 1;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
inline int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache, bool cmos_cost)
|
dict<RTLIL::IdString, int> mod_cost_cache;
|
||||||
{
|
const dict<RTLIL::IdString, int> *gate_cost = nullptr;
|
||||||
return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache, cmos_cost);
|
Design *design = nullptr;
|
||||||
}
|
|
||||||
|
int get(RTLIL::IdString type) const
|
||||||
|
{
|
||||||
|
if (gate_cost && gate_cost->count(type))
|
||||||
|
return gate_cost->at(type);
|
||||||
|
|
||||||
|
log_warning("Can't determine cost of %s cell.\n", log_id(type));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get(RTLIL::Cell *cell)
|
||||||
|
{
|
||||||
|
if (gate_cost && gate_cost->count(cell->type))
|
||||||
|
return gate_cost->at(cell->type);
|
||||||
|
|
||||||
|
if (design && design->module(cell->type) && cell->parameters.empty())
|
||||||
|
{
|
||||||
|
RTLIL::Module *mod = design->module(cell->type);
|
||||||
|
|
||||||
|
if (mod->attributes.count("\\cost"))
|
||||||
|
return mod->attributes.at("\\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;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(cell->type), GetSize(cell->parameters));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
YOSYS_NAMESPACE_END
|
YOSYS_NAMESPACE_END
|
||||||
|
|
||||||
|
|
|
@ -931,9 +931,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
||||||
{
|
{
|
||||||
log_header(design, "Executing ABC.\n");
|
log_header(design, "Executing ABC.\n");
|
||||||
|
|
||||||
auto cell_cost = [](IdString cell_type) {
|
auto &cell_cost = cmos_cost ? CellCosts::cmos_gate_cost() : CellCosts::default_gate_cost();
|
||||||
return get_cell_cost(cell_type, dict<RTLIL::IdString, RTLIL::Const>(), nullptr, nullptr, cmos_cost);
|
|
||||||
};
|
|
||||||
|
|
||||||
buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str());
|
buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str());
|
||||||
f = fopen(buffer.c_str(), "wt");
|
f = fopen(buffer.c_str(), "wt");
|
||||||
|
@ -941,42 +939,42 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
||||||
log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
|
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 ZERO 1 Y=CONST0;\n");
|
||||||
fprintf(f, "GATE ONE 1 Y=CONST1;\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 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("$_NOT_"));
|
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"))
|
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"))
|
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"))
|
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"))
|
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"))
|
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"))
|
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"))
|
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"))
|
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"))
|
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"))
|
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"))
|
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"))
|
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"))
|
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"))
|
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)
|
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)
|
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)
|
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);
|
fclose(f);
|
||||||
|
|
||||||
if (!lut_costs.empty()) {
|
if (!lut_costs.empty()) {
|
||||||
|
|
Loading…
Reference in New Issue