mirror of https://github.com/YosysHQ/yosys.git
zinit: Refactor to use FfData.
This commit is contained in:
parent
63b9df8693
commit
ba0723cad7
|
@ -20,10 +20,19 @@
|
|||
#include "kernel/yosys.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/ffinit.h"
|
||||
#include "kernel/ff.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
State invert(State s) {
|
||||
switch (s) {
|
||||
case State::S0: return State::S1;
|
||||
case State::S1: return State::S0;
|
||||
default: return s;
|
||||
}
|
||||
}
|
||||
|
||||
struct ZinitPass : public Pass {
|
||||
ZinitPass() : Pass("zinit", "add inverters so all FF are zero-initialized") { }
|
||||
void help() override
|
||||
|
@ -60,123 +69,51 @@ struct ZinitPass : public Pass {
|
|||
SigMap sigmap(module);
|
||||
FfInitVals initvals(&sigmap, module);
|
||||
|
||||
pool<IdString> dff_types = {
|
||||
// FIXME: It would appear that supporting
|
||||
// $dffsr/$_DFFSR_* would require a new
|
||||
// cell type where S has priority over R
|
||||
ID($ff), ID($dff), ID($dffe), /*ID($dffsr),*/ ID($adff), ID($adffe),
|
||||
ID($sdff), ID($sdffe), ID($sdffce),
|
||||
ID($_FF_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
|
||||
/*ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
|
||||
ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),*/
|
||||
ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
|
||||
ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
|
||||
// Async set/reset
|
||||
ID($_DFFE_NN0P_), ID($_DFFE_NN1P_), ID($_DFFE_NP0P_), ID($_DFFE_NP1P_),
|
||||
ID($_DFFE_PN0P_), ID($_DFFE_PN1P_), ID($_DFFE_PP0P_), ID($_DFFE_PP1P_),
|
||||
ID($_DFFE_NN0N_), ID($_DFFE_NN1N_), ID($_DFFE_NP0N_), ID($_DFFE_NP1N_),
|
||||
ID($_DFFE_PN0N_), ID($_DFFE_PN1N_), ID($_DFFE_PP0N_), ID($_DFFE_PP1N_),
|
||||
// Sync set/reset
|
||||
ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_),
|
||||
ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_),
|
||||
ID($_SDFFE_NN0P_), ID($_SDFFE_NN1P_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1P_),
|
||||
ID($_SDFFE_PN0P_), ID($_SDFFE_PN1P_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1P_),
|
||||
ID($_SDFFE_NN0N_), ID($_SDFFE_NN1N_), ID($_SDFFE_NP0N_), ID($_SDFFE_NP1N_),
|
||||
ID($_SDFFE_PN0N_), ID($_SDFFE_PN1N_), ID($_SDFFE_PP0N_), ID($_SDFFE_PP1N_),
|
||||
ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1P_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1P_),
|
||||
ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1P_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1P_),
|
||||
ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP1N_),
|
||||
ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP1N_)
|
||||
};
|
||||
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
if (!dff_types.count(cell->type))
|
||||
if (!RTLIL::builtin_ff_cell_types().count(cell->type))
|
||||
continue;
|
||||
|
||||
SigSpec sig_d = sigmap(cell->getPort(ID::D));
|
||||
SigSpec sig_q = sigmap(cell->getPort(ID::Q));
|
||||
|
||||
if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
|
||||
FfData ff(&initvals, cell);
|
||||
if (!ff.width)
|
||||
continue;
|
||||
|
||||
Const initval = initvals(sig_q);
|
||||
Const newval = initval;
|
||||
initvals.remove_init(sig_q);
|
||||
// Supporting those would require a new cell type where S has priority over R.
|
||||
if (ff.has_sr)
|
||||
continue;
|
||||
|
||||
Wire *initwire = module->addWire(NEW_ID, GetSize(sig_q));
|
||||
Wire *new_q = module->addWire(NEW_ID, ff.width);
|
||||
|
||||
for (int i = 0; i < GetSize(initwire); i++)
|
||||
if (initval[i] == State::S1)
|
||||
log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type),
|
||||
log_signal(ff.sig_q), log_signal(ff.val_init));
|
||||
|
||||
IdString name = cell->name;
|
||||
module->remove(cell);
|
||||
initvals.remove_init(ff.sig_q);
|
||||
|
||||
for (int i = 0; i < ff.width; i++)
|
||||
if (ff.val_init[i] == State::S1)
|
||||
{
|
||||
sig_d[i] = module->NotGate(NEW_ID, sig_d[i]);
|
||||
module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]);
|
||||
newval[i] = State::S0;
|
||||
if (ff.has_clk || ff.has_gclk)
|
||||
ff.sig_d[i] = module->NotGate(NEW_ID, ff.sig_d[i]);
|
||||
if (ff.has_aload)
|
||||
ff.sig_ad[i] = module->NotGate(NEW_ID, ff.sig_ad[i]);
|
||||
if (ff.has_arst)
|
||||
ff.val_arst[i] = invert(ff.val_arst[i]);
|
||||
if (ff.has_srst)
|
||||
ff.val_srst[i] = invert(ff.val_srst[i]);
|
||||
module->addNotGate(NEW_ID, SigSpec(new_q, i), ff.sig_q[i]);
|
||||
ff.val_init[i] = State::S0;
|
||||
}
|
||||
else
|
||||
{
|
||||
module->connect(sig_q[i], SigSpec(initwire, i));
|
||||
module->connect(ff.sig_q[i], SigSpec(new_q, i));
|
||||
if (all_mode)
|
||||
newval[i] = State::S0;
|
||||
ff.val_init[i] = State::S0;
|
||||
}
|
||||
|
||||
initvals.set_init(initwire, newval);
|
||||
|
||||
log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type),
|
||||
log_signal(sig_q), log_signal(initval));
|
||||
|
||||
cell->setPort(ID::D, sig_d);
|
||||
cell->setPort(ID::Q, initwire);
|
||||
|
||||
if (cell->type.in(ID($adff), ID($adffe))) {
|
||||
auto val = cell->getParam(ID::ARST_VALUE);
|
||||
for (int i = 0; i < GetSize(initwire); i++)
|
||||
if (initval[i] == State::S1)
|
||||
val[i] = (val[i] == State::S1 ? State::S0 : State::S1);
|
||||
cell->setParam(ID::ARST_VALUE, std::move(val));
|
||||
}
|
||||
else if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) {
|
||||
auto val = cell->getParam(ID::SRST_VALUE);
|
||||
for (int i = 0; i < GetSize(initwire); i++)
|
||||
if (initval[i] == State::S1)
|
||||
val[i] = (val[i] == State::S1 ? State::S0 : State::S1);
|
||||
cell->setParam(ID::SRST_VALUE, std::move(val));
|
||||
}
|
||||
else if (initval == State::S1) {
|
||||
std::string t = cell->type.str();
|
||||
if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
|
||||
ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)))
|
||||
{
|
||||
t[8] = (t[8] == '0' ? '1' : '0');
|
||||
}
|
||||
else if (cell->type.in(ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_),
|
||||
ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_)))
|
||||
{
|
||||
t[9] = (t[9] == '0' ? '1' : '0');
|
||||
}
|
||||
else if (cell->type.in(ID($_DFFE_NN0P_), ID($_DFFE_NN1P_), ID($_DFFE_NP0P_), ID($_DFFE_NP1P_),
|
||||
ID($_DFFE_PN0P_), ID($_DFFE_PN1P_), ID($_DFFE_PP0P_), ID($_DFFE_PP1P_),
|
||||
ID($_DFFE_NN0N_), ID($_DFFE_NN1N_), ID($_DFFE_NP0N_), ID($_DFFE_NP1N_),
|
||||
ID($_DFFE_PN0N_), ID($_DFFE_PN1N_), ID($_DFFE_PP0N_), ID($_DFFE_PP1N_)))
|
||||
{
|
||||
t[9] = (t[9] == '0' ? '1' : '0');
|
||||
}
|
||||
else if (cell->type.in(ID($_SDFFE_NN0P_), ID($_SDFFE_NN1P_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1P_),
|
||||
ID($_SDFFE_PN0P_), ID($_SDFFE_PN1P_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1P_),
|
||||
ID($_SDFFE_NN0N_), ID($_SDFFE_NN1N_), ID($_SDFFE_NP0N_), ID($_SDFFE_NP1N_),
|
||||
ID($_SDFFE_PN0N_), ID($_SDFFE_PN1N_), ID($_SDFFE_PP0N_), ID($_SDFFE_PP1N_)))
|
||||
{
|
||||
t[10] = (t[10] == '0' ? '1' : '0');
|
||||
}
|
||||
else if (cell->type.in(ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1P_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1P_),
|
||||
ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1P_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1P_),
|
||||
ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP1N_),
|
||||
ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP1N_)))
|
||||
{
|
||||
t[11] = (t[11] == '0' ? '1' : '0');
|
||||
}
|
||||
cell->type = t;
|
||||
}
|
||||
ff.sig_q = new_q;
|
||||
ff.emit(module, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue