Improved handling of reg init in opt_share and opt_rmdff

This commit is contained in:
Clifford Wolf 2014-02-04 12:02:47 +01:00
parent 9e938aa32a
commit ecdf1f5577
2 changed files with 48 additions and 7 deletions

View File

@ -24,7 +24,7 @@
#include <stdlib.h>
#include <stdio.h>
static SigMap assign_map;
static SigMap assign_map, dff_init_map;
static SigSet<RTLIL::Cell*> mux_drivers;
static bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
@ -73,6 +73,14 @@ static bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
assign_map.apply(sig_c);
assign_map.apply(sig_r);
bool has_init;
RTLIL::Const val_init;
for (auto bit : dff_init_map(sig_q).to_sigbit_vector()) {
if (bit.wire == NULL)
has_init = true;
val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx);
}
if (dff->type == "$dff" && mux_drivers.has(sig_d)) {
std::set<RTLIL::Cell*> muxes;
mux_drivers.find(sig_d, muxes);
@ -92,31 +100,41 @@ static bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
}
}
if (sig_c.is_fully_const()) {
if (sig_c.is_fully_const() && (!sig_r.width || !has_init)) {
if (val_rv.bits.size() == 0)
val_rv = RTLIL::Const(RTLIL::State::Sx, sig_q.width);
val_rv = val_init;
RTLIL::SigSig conn(sig_q, val_rv);
mod->connections.push_back(conn);
goto delete_dff;
}
if (sig_d.is_fully_undef() && sig_d.width == int(val_rv.bits.size())) {
if (sig_d.is_fully_undef() && sig_r.width && !has_init) {
RTLIL::SigSig conn(sig_q, val_rv);
mod->connections.push_back(conn);
goto delete_dff;
}
if (sig_d.is_fully_const() && sig_r.width == 0) {
if (sig_d.is_fully_undef() && !sig_r.width && has_init) {
RTLIL::SigSig conn(sig_q, val_init);
mod->connections.push_back(conn);
goto delete_dff;
}
if (sig_d.is_fully_const() && !sig_r.width && !has_init) {
RTLIL::SigSig conn(sig_q, sig_d);
mod->connections.push_back(conn);
goto delete_dff;
}
if (sig_d == sig_q) {
if (sig_r.width > 0) {
if (sig_d == sig_q && !(sig_r.width && has_init)) {
if (sig_r.width) {
RTLIL::SigSig conn(sig_q, val_rv);
mod->connections.push_back(conn);
}
if (has_init) {
RTLIL::SigSig conn(sig_q, val_init);
mod->connections.push_back(conn);
}
goto delete_dff;
}
@ -155,6 +173,10 @@ struct OptRmdffPass : public Pass {
continue;
assign_map.set(mod_it.second);
dff_init_map.set(mod_it.second);
for (auto &it : mod_it.second->wires)
if (it.second->attributes.count("\\init") != 0)
dff_init_map.add(it.second, it.second->attributes.at("\\init"));
mux_drivers.clear();
std::vector<std::string> dff_list;

View File

@ -35,6 +35,7 @@ struct OptShareWorker
RTLIL::Design *design;
RTLIL::Module *module;
SigMap assign_map;
SigMap dff_init_map;
CellTypes ct;
int total_count;
@ -178,6 +179,16 @@ struct OptShareWorker
return true;
}
if (cell1->type.substr(0, 1) == "$" && conn1.count("\\Q") != 0) {
std::vector<RTLIL::SigBit> q1 = dff_init_map(cell1->connections.at("\\Q")).to_sigbit_vector();
std::vector<RTLIL::SigBit> q2 = dff_init_map(cell2->connections.at("\\Q")).to_sigbit_vector();
for (size_t i = 0; i < q1.size(); i++)
if ((q1.at(i).wire == NULL || q2.at(i).wire == NULL) && q1.at(i) != q2.at(i)) {
lt = q1.at(i) < q2.at(i);
return true;
}
}
return false;
}
@ -189,6 +200,9 @@ struct OptShareWorker
if (!ct.cell_known(cell1->type))
return cell1 < cell2;
if (cell1->get_bool_attribute("\\keep") || cell2->get_bool_attribute("\\keep"))
return cell1 < cell2;
bool lt;
if (compare_cell_parameters_and_connections(cell1, cell2, lt))
return lt;
@ -222,6 +236,11 @@ struct OptShareWorker
log("Finding identical cells in module `%s'.\n", module->name.c_str());
assign_map.set(module);
dff_init_map.set(module);
for (auto &it : module->wires)
if (it.second->attributes.count("\\init") != 0)
dff_init_map.add(it.second, it.second->attributes.at("\\init"));
bool did_something = true;
while (did_something)
{