Added "dff2dffe -direct" for direct gate mapping

This commit is contained in:
Clifford Wolf 2014-12-24 11:39:15 +01:00
parent 8c1a72c2a4
commit 032ce573a3
1 changed files with 37 additions and 5 deletions

View File

@ -31,6 +31,8 @@ struct Dff2dffeWorker
SigMap sigmap;
CellTypes ct;
RTLIL::IdString direct_to;
typedef std::pair<RTLIL::Cell*, int> cell_int_t;
std::map<RTLIL::SigBit, cell_int_t> bit2mux;
std::vector<RTLIL::Cell*> dff_cells;
@ -39,7 +41,9 @@ struct Dff2dffeWorker
typedef std::map<RTLIL::SigBit, bool> pattern_t;
typedef std::set<pattern_t> patterns_t;
Dff2dffeWorker(RTLIL::Module *module) : module(module), sigmap(module), ct(module->design)
Dff2dffeWorker(RTLIL::Module *module, RTLIL::IdString direct_from, RTLIL::IdString direct_to) :
module(module), sigmap(module), ct(module->design), direct_to(direct_to)
{
for (auto wire : module->wires()) {
if (wire->port_output)
@ -53,8 +57,13 @@ struct Dff2dffeWorker
for (int i = 0; i < GetSize(sig_y); i++)
bit2mux[sig_y[i]] = cell_int_t(cell, i);
}
if (cell->type == "$dff" || cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_")
dff_cells.push_back(cell);
if (direct_to.empty()) {
if (cell->type == "$dff" || cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_")
dff_cells.push_back(cell);
} else {
if (cell->type == direct_from)
dff_cells.push_back(cell);
}
for (auto conn : cell->connections()) {
if (ct.cell_output(cell->type, conn.first))
continue;
@ -197,6 +206,11 @@ struct Dff2dffeWorker
new_sig_d.append(sig_d[i]);
new_sig_q.append(sig_q[i]);
}
if (!direct_to.empty()) {
log(" converting %s cell %s to %s for %s -> %s.\n", log_id(dff_cell->type), log_id(dff_cell), log_id(direct_to), log_signal(new_sig_d), log_signal(new_sig_q));
dff_cell->setPort("\\E", make_patterns_logic(it.first, true));
dff_cell->type = direct_to;
} else
if (dff_cell->type == "$dff") {
RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort("\\CLK"), make_patterns_logic(it.first, false),
new_sig_d, new_sig_q, dff_cell->getParam("\\CLK_POLARITY").as_bool(), true);
@ -208,6 +222,9 @@ struct Dff2dffeWorker
}
}
if (!direct_to.empty())
return;
if (remaining_indices.empty()) {
log(" removing now obsolete cell %s.\n", log_id(dff_cell));
module->remove(dff_cell);
@ -246,7 +263,16 @@ struct Dff2dffePass : public Pass {
log("\n");
log(" -unmap\n");
log(" operate in the opposite direction: replace $dffe cells with combinations\n");
log(" of $dff and $mux cells\n");
log(" of $dff and $mux cells. the options below are ignore in unmap mode.\n");
log("\n");
log(" -direct <internal_gate_type> <external_gate_type>\n");
log(" map directly to external gate type. <internal_gate_type> can\n");
log(" be any internal gate-level FF cell (except $_DFFE_??_). the\n");
log(" <external_gate_type> is the cell type name for a cell with an\n");
log(" identical interface to the <internal_gate_type>, except it\n");
log(" also has an high-active enable port 'E'.\n");
log(" Usually <external_gate_type> is an intemediate cell type\n");
log(" that is then translated to the final type using 'techmap'.\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
@ -254,6 +280,7 @@ struct Dff2dffePass : public Pass {
log_header("Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n");
bool unmap_mode = false;
RTLIL::IdString direct_from, direct_to;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
@ -261,6 +288,11 @@ struct Dff2dffePass : public Pass {
unmap_mode = true;
continue;
}
if (args[argidx] == "-direct" && argidx + 2 < args.size()) {
direct_from = RTLIL::escape_id(args[++argidx]);
direct_to = RTLIL::escape_id(args[++argidx]);
continue;
}
break;
}
extra_args(args, argidx, design);
@ -296,7 +328,7 @@ struct Dff2dffePass : public Pass {
continue;
}
Dff2dffeWorker worker(mod);
Dff2dffeWorker worker(mod, direct_from, direct_to);
worker.run();
}
}