mirror of https://github.com/YosysHQ/yosys.git
Add support for set-reset cell variants to opt_rmdff
This commit is contained in:
parent
159701962a
commit
007f29b9c2
|
@ -39,6 +39,175 @@ void remove_init_attr(SigSpec sig)
|
|||
wbit.wire->attributes.at("\\init")[wbit.offset] = State::Sx;
|
||||
}
|
||||
|
||||
bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
|
||||
{
|
||||
SigSpec sig_set, sig_clr;
|
||||
State pol_set, pol_clr;
|
||||
|
||||
if (cell->hasPort("\\S"))
|
||||
sig_set = cell->getPort("\\S");
|
||||
|
||||
if (cell->hasPort("\\R"))
|
||||
sig_clr = cell->getPort("\\R");
|
||||
|
||||
if (cell->hasPort("\\SET"))
|
||||
sig_set = cell->getPort("\\SET");
|
||||
|
||||
if (cell->hasPort("\\CLR"))
|
||||
sig_clr = cell->getPort("\\CLR");
|
||||
|
||||
log_assert(GetSize(sig_set) == GetSize(sig_clr));
|
||||
|
||||
if (cell->type.substr(0,8) == "$_DFFSR_") {
|
||||
pol_set = cell->type[9] == 'P' ? State::S1 : State::S0;
|
||||
pol_clr = cell->type[10] == 'P' ? State::S1 : State::S0;
|
||||
} else
|
||||
if (cell->type.substr(0,11) == "$_DLATCHSR_") {
|
||||
pol_set = cell->type[12] == 'P' ? State::S1 : State::S0;
|
||||
pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0;
|
||||
} else
|
||||
if (cell->type == "$dffsr" || cell->type == "$dlatchsr") {
|
||||
pol_set = cell->parameters["\\SET_POLARITY"].as_bool() ? State::S1 : State::S0;
|
||||
pol_clr = cell->parameters["\\CLR_POLARITY"].as_bool() ? State::S1 : State::S0;
|
||||
} else
|
||||
log_abort();
|
||||
|
||||
State npol_set = pol_set == State::S0 ? State::S1 : State::S0;
|
||||
State npol_clr = pol_clr == State::S0 ? State::S1 : State::S0;
|
||||
|
||||
SigSpec sig_d = cell->getPort("\\D");
|
||||
SigSpec sig_q = cell->getPort("\\Q");
|
||||
|
||||
bool did_something = false;
|
||||
bool proper_sr = false;
|
||||
bool used_pol_set = false;
|
||||
bool used_pol_clr = false;
|
||||
bool hasreset = false;
|
||||
Const reset_val;
|
||||
SigSpec sig_reset;
|
||||
|
||||
for (int i = 0; i < GetSize(sig_set); i++)
|
||||
{
|
||||
SigBit s = sig_set[i], c = sig_clr[i];
|
||||
|
||||
if (s != npol_set || c != npol_clr)
|
||||
hasreset = true;
|
||||
|
||||
if (s == pol_set || c == pol_clr)
|
||||
{
|
||||
log("Constantly %s Q bit %s for SR cell %s (%s) from module %s.\n",
|
||||
s == pol_set ? "set" : "cleared", log_signal(sig_q[i]),
|
||||
log_id(cell), log_id(cell->type), log_id(mod));
|
||||
|
||||
remove_init_attr(sig_q[i]);
|
||||
mod->connect(sig_q[i], s == pol_set ? State::S1 : State::S0);
|
||||
sig_set.remove(i);
|
||||
sig_clr.remove(i);
|
||||
sig_d.remove(i);
|
||||
sig_q.remove(i--);
|
||||
did_something = true;
|
||||
continue;
|
||||
}
|
||||
if (sig_reset.empty() && s.wire != nullptr) sig_reset = s;
|
||||
if (sig_reset.empty() && c.wire != nullptr) sig_reset = c;
|
||||
|
||||
if (s.wire != nullptr && s != sig_reset) proper_sr = true;
|
||||
if (c.wire != nullptr && c != sig_reset) proper_sr = true;
|
||||
|
||||
if ((s.wire == nullptr) != (c.wire == nullptr)) {
|
||||
if (s.wire != nullptr) used_pol_set = true;
|
||||
if (c.wire != nullptr) used_pol_clr = true;
|
||||
reset_val.bits.push_back(c.wire == nullptr ? State::S1 : State::S0);
|
||||
} else
|
||||
proper_sr = true;
|
||||
}
|
||||
|
||||
if (!hasreset)
|
||||
proper_sr = false;
|
||||
|
||||
if (GetSize(sig_set) == 0)
|
||||
{
|
||||
log("Removing %s (%s) from module %s.\n", log_id(cell), log_id(cell->type), log_id(mod));
|
||||
mod->remove(cell);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == "$dffsr" || cell->type == "$dlatchsr")
|
||||
{
|
||||
cell->setParam("\\WIDTH", GetSize(sig_d));
|
||||
cell->setPort("\\SET", sig_set);
|
||||
cell->setPort("\\CLR", sig_clr);
|
||||
cell->setPort("\\D", sig_d);
|
||||
cell->setPort("\\Q", sig_q);
|
||||
}
|
||||
else
|
||||
{
|
||||
cell->setPort("\\S", sig_set);
|
||||
cell->setPort("\\R", sig_clr);
|
||||
cell->setPort("\\D", sig_d);
|
||||
cell->setPort("\\Q", sig_q);
|
||||
}
|
||||
|
||||
if (proper_sr)
|
||||
return did_something;
|
||||
|
||||
if (used_pol_set && used_pol_clr && pol_set != pol_clr)
|
||||
return did_something;
|
||||
|
||||
State unified_pol = used_pol_set ? pol_set : pol_clr;
|
||||
|
||||
if (cell->type == "$dffsr")
|
||||
{
|
||||
if (hasreset)
|
||||
{
|
||||
log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$adff", log_id(mod));
|
||||
|
||||
cell->type = "$adff";
|
||||
cell->setParam("\\ARST_POLARITY", unified_pol);
|
||||
cell->setParam("\\ARST_VALUE", reset_val);
|
||||
cell->setPort("\\ARST", sig_reset);
|
||||
|
||||
cell->unsetParam("\\SET_POLARITY");
|
||||
cell->unsetParam("\\CLR_POLARITY");
|
||||
cell->unsetPort("\\SET");
|
||||
cell->unsetPort("\\CLR");
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$dff", log_id(mod));
|
||||
|
||||
cell->type = "$dff";
|
||||
cell->unsetParam("\\SET_POLARITY");
|
||||
cell->unsetParam("\\CLR_POLARITY");
|
||||
cell->unsetPort("\\SET");
|
||||
cell->unsetPort("\\CLR");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IdString new_type;
|
||||
|
||||
if (cell->type.substr(0,8) == "$_DFFSR_")
|
||||
new_type = stringf("$_DFF_%c_", cell->type[8]);
|
||||
else if (cell->type.substr(0,11) == "$_DLATCHSR_")
|
||||
new_type = stringf("$_DLATCH_%c_", cell->type[11]);
|
||||
else
|
||||
log_abort();
|
||||
|
||||
log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), log_id(new_type), log_id(mod));
|
||||
|
||||
cell->type = new_type;
|
||||
cell->unsetPort("\\S");
|
||||
cell->unsetPort("\\R");
|
||||
|
||||
return did_something;
|
||||
}
|
||||
}
|
||||
|
||||
bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
|
||||
{
|
||||
SigSpec sig_e;
|
||||
|
@ -287,6 +456,7 @@ struct OptRmdffPass : public Pass {
|
|||
mux_drivers.clear();
|
||||
|
||||
std::vector<RTLIL::IdString> dff_list;
|
||||
std::vector<RTLIL::IdString> dffsr_list;
|
||||
std::vector<RTLIL::IdString> dlatch_list;
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
|
@ -304,6 +474,12 @@ struct OptRmdffPass : public Pass {
|
|||
if (!design->selected(module, cell))
|
||||
continue;
|
||||
|
||||
if (cell->type.in("$_DFFSR_NNN_", "$_DFFSR_NNP_", "$_DFFSR_NPN_", "$_DFFSR_NPP_",
|
||||
"$_DFFSR_PNN_", "$_DFFSR_PNP_", "$_DFFSR_PPN_", "$_DFFSR_PPP_", "$dffsr",
|
||||
"$_DLATCHSR_NNN_", "$_DLATCHSR_NNP_", "$_DLATCHSR_NPN_", "$_DLATCHSR_NPP_",
|
||||
"$_DLATCHSR_PNN_", "$_DLATCHSR_PNP_", "$_DLATCHSR_PPN_", "$_DLATCHSR_PPP_", "$dlatchsr"))
|
||||
dffsr_list.push_back(cell->name);
|
||||
|
||||
if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_",
|
||||
"$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
|
||||
"$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_",
|
||||
|
@ -314,6 +490,12 @@ struct OptRmdffPass : public Pass {
|
|||
dlatch_list.push_back(cell->name);
|
||||
}
|
||||
|
||||
for (auto &id : dffsr_list) {
|
||||
if (module->cell(id) != nullptr &&
|
||||
handle_dffsr(module, module->cells_[id]))
|
||||
total_count++;
|
||||
}
|
||||
|
||||
for (auto &id : dff_list) {
|
||||
if (module->cell(id) != nullptr &&
|
||||
handle_dff(module, module->cells_[id]))
|
||||
|
|
Loading…
Reference in New Issue