Skip to content

Commit

Permalink
cost: start adding support for non-techmapped cells
Browse files Browse the repository at this point in the history
  • Loading branch information
Emil Tywoniak authored and Emil Tywoniak committed Apr 11, 2024
1 parent bae5009 commit 5718700
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 74 deletions.
8 changes: 8 additions & 0 deletions kernel/cost.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include "kernel/cost.h"

USING_YOSYS_NAMESPACE

CellCosts::CellCosts(CellCosts::CostKind kind, RTLIL::Design *design) : kind(kind), design(design) {
}


76 changes: 44 additions & 32 deletions kernel/cost.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,23 @@ YOSYS_NAMESPACE_BEGIN

struct CellCosts
{
static const dict<RTLIL::IdString, int>& default_gate_cost() {
static const dict<RTLIL::IdString, int> db = {

enum CostKind {
DEFAULT,
CMOS,
};

private:
dict<RTLIL::IdString, int> mod_cost_cache;
CostKind kind;
Design *design = nullptr;
bool type_only;

public:
CellCosts(CostKind kind, Design *design);

const dict<RTLIL::IdString, int>& gate_type_cost() {
static const dict<RTLIL::IdString, int> default_gate_db = {
{ ID($_BUF_), 1 },
{ ID($_NOT_), 2 },
{ ID($_AND_), 4 },
Expand All @@ -47,11 +62,8 @@ struct CellCosts
{ ID($_DFF_P_), 1 },
{ ID($_DFF_N_), 1 },
};
return db;
}

static const dict<RTLIL::IdString, int>& cmos_gate_cost() {
static const dict<RTLIL::IdString, int> db = {
static const dict<RTLIL::IdString, int> cmos_transistors_db = {
{ ID($_BUF_), 1 },
{ ID($_NOT_), 2 },
{ ID($_AND_), 6 },
Expand All @@ -71,43 +83,43 @@ struct CellCosts
{ ID($_DFF_P_), 16 },
{ ID($_DFF_N_), 16 },
};
return db;
switch (kind) {
case DEFAULT:
return default_gate_db;
case CMOS:
return cmos_transistors_db;
default:
log_assert(false && "Unreachable: Invalid cell cost kind\n");
}
}

dict<RTLIL::IdString, int> mod_cost_cache;
const dict<RTLIL::IdString, int> *gate_cost = nullptr;
Design *design = nullptr;

int get(RTLIL::IdString type) const
int get(RTLIL::Module *mod)
{
if (gate_cost && gate_cost->count(type))
return gate_cost->at(type);
if (mod->attributes.count(ID(cost)))
return mod->attributes.at(ID(cost)).as_int();

log_warning("Can't determine cost of %s cell.\n", log_id(type));
return 1;
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_cost && gate_cost->count(cell->type))
return gate_cost->at(cell->type);
if (gate_type_cost().count(cell->type))
return gate_type_cost().at(cell->type);

if (design && design->module(cell->type) && cell->parameters.empty())
{
RTLIL::Module *mod = design->module(cell->type);

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;
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));
Expand Down
8 changes: 5 additions & 3 deletions passes/cmds/stat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -222,14 +222,16 @@ struct statdata_t
unsigned int cmos_transistor_count(bool *tran_cnt_exact)
{
unsigned int tran_cnt = 0;
auto &gate_costs = CellCosts::cmos_gate_cost();
auto cost_kind = CellCosts::CMOS;
CellCosts costs(cost_kind, nullptr);
auto cell_type_cost = costs.gate_type_cost();

for (auto it : num_cells_by_type) {
auto ctype = it.first;
auto cnum = it.second;

if (gate_costs.count(ctype))
tran_cnt += cnum * gate_costs.at(ctype);
if (cell_type_cost.count(ctype))
tran_cnt += cnum * cell_type_cost.at(ctype);
else
*tran_cnt_exact = false;
}
Expand Down
33 changes: 14 additions & 19 deletions passes/hierarchy/cellestimate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,44 +41,39 @@ struct CellEstimatePass : public Pass {
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
bool cmos_cost = false;
CellCosts::CostKind cost_kind = CellCosts::DEFAULT;

log_header(design, "Executing cell estimate pass.\n");

size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-cmos") {
cmos_cost = true;
cost_kind = CellCosts::CMOS;
continue;
}
break;
}
extra_args(args, argidx, design);

int cells_known_cost = 0;
int cell_count = 0;
// int cells_known_cost = 0;
// int cell_count = 0;

CellCosts costs(cost_kind, design);

for (auto module : design->selected_modules()) {

int module_cost = 0;
// TODO should we really respect cell selection?
for (auto cell : module->selected_cells()) {
cell_count++;

auto &cell_cost = cmos_cost ? CellCosts::cmos_gate_cost() : CellCosts::default_gate_cost();
bool has_known_cost = (bool)cell_cost.count(cell->type);
if (has_known_cost)
cells_known_cost++;

int cost = has_known_cost ? cell_cost.at(cell->type) : 1;
log_debug("Cost for cell %s (%s): %d\n", log_id(cell), log_id(cell->type), cost);
module_cost += cost;
}
// for (auto cell : module->selected_cells()) {
// log_debug("Cost for cell %s (%s): %d\n", log_id(cell), log_id(cell->type), cost);
// }
module_cost = costs.get(module);
log("Cost estimate for module %s: %d\n", log_id(module->name), module_cost);
module->attributes[ID::cost] = module_cost;
}
float known_percent = (static_cast<double>(cells_known_cost) / cell_count) * 100.0;
if (!std::isnan(known_percent))
log("Cost estimates known for %.0f%% cells\n", known_percent);
// float known_percent = (static_cast<double>(cells_known_cost) / cell_count) * 100.0;
// if (!std::isnan(known_percent))
// log("Cost estimates known for %.0f%% cells\n", known_percent);
}
} ZinitPass;

Expand Down
42 changes: 22 additions & 20 deletions passes/techmap/abc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1047,50 +1047,52 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
{
log_header(design, "Executing ABC.\n");

auto &cell_cost = cmos_cost ? CellCosts::cmos_gate_cost() : CellCosts::default_gate_cost();
auto cost_kind = cmos_cost ? CellCosts::CMOS : CellCosts::DEFAULT;
CellCosts costs(cost_kind, design);
auto cell_type_cost = costs.gate_type_cost();

buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str());
f = fopen(buffer.c_str(), "wt");
if (f == nullptr)
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.at(ID($_BUF_)));
fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NOT_)));
fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", cell_type_cost.at(ID($_BUF_)));
fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_type_cost.at(ID($_NOT_)));
if (enabled_gates.count("AND"))
fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_AND_)));
fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_type_cost.at(ID($_AND_)));
if (enabled_gates.count("NAND"))
fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NAND_)));
fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_type_cost.at(ID($_NAND_)));
if (enabled_gates.count("OR"))
fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_OR_)));
fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_type_cost.at(ID($_OR_)));
if (enabled_gates.count("NOR"))
fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NOR_)));
fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_type_cost.at(ID($_NOR_)));
if (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.at(ID($_XOR_)));
fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_type_cost.at(ID($_XOR_)));
if (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.at(ID($_XNOR_)));
fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_type_cost.at(ID($_XNOR_)));
if (enabled_gates.count("ANDNOT"))
fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_ANDNOT_)));
fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_type_cost.at(ID($_ANDNOT_)));
if (enabled_gates.count("ORNOT"))
fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_ORNOT_)));
fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_type_cost.at(ID($_ORNOT_)));
if (enabled_gates.count("AOI3"))
fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_AOI3_)));
fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_type_cost.at(ID($_AOI3_)));
if (enabled_gates.count("OAI3"))
fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_OAI3_)));
fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_type_cost.at(ID($_OAI3_)));
if (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.at(ID($_AOI4_)));
fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", cell_type_cost.at(ID($_AOI4_)));
if (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.at(ID($_OAI4_)));
fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", cell_type_cost.at(ID($_OAI4_)));
if (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.at(ID($_MUX_)));
fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_type_cost.at(ID($_MUX_)));
if (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.at(ID($_NMUX_)));
fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_type_cost.at(ID($_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.at(ID($_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_type_cost.at(ID($_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.at(ID($_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_type_cost.at(ID($_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.at(ID($_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_type_cost.at(ID($_MUX_)));
fclose(f);

if (!lut_costs.empty()) {
Expand Down

0 comments on commit 5718700

Please sign in to comment.