aboutsummaryrefslogtreecommitdiffstats
path: root/passes/techmap/zinit.cc
diff options
context:
space:
mode:
Diffstat (limited to 'passes/techmap/zinit.cc')
-rw-r--r--passes/techmap/zinit.cc72
1 files changed, 54 insertions, 18 deletions
diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc
index a427c4987..74604ba3b 100644
--- a/passes/techmap/zinit.cc
+++ b/passes/techmap/zinit.cc
@@ -57,8 +57,7 @@ struct ZinitPass : public Pass {
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
- dict<SigBit, State> initbits;
- pool<SigBit> donebits;
+ dict<SigBit, std::pair<State,SigBit>> initbits;
for (auto wire : module->selected_wires())
{
@@ -67,7 +66,6 @@ struct ZinitPass : public Pass {
SigSpec wirebits = sigmap(wire);
Const initval = wire->attributes.at(ID::init);
- wire->attributes.erase(ID::init);
for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
{
@@ -78,24 +76,35 @@ struct ZinitPass : public Pass {
continue;
if (initbits.count(bit)) {
- if (initbits.at(bit) != val)
+ if (initbits.at(bit).first != val)
log_error("Conflicting init values for signal %s (%s = %s != %s).\n",
log_signal(bit), log_signal(SigBit(wire, i)),
- log_signal(val), log_signal(initbits.at(bit)));
+ log_signal(val), log_signal(initbits.at(bit).first));
continue;
}
- initbits[bit] = val;
+ initbits[bit] = std::make_pair(val,SigBit(wire,i));
}
}
pool<IdString> dff_types = {
- ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($adff),
+ // 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($_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($_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_)
+ ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
+ // Async set/reset
+ ID($__DFFE_NN0), ID($__DFFE_NN1), ID($__DFFE_NP0), ID($__DFFE_NP1),
+ ID($__DFFE_PN0), ID($__DFFE_PN1), ID($__DFFE_PP0), ID($__DFFE_PP1),
+ // Sync set/reset
+ ID($__DFFS_NN0_), ID($__DFFS_NN1_), ID($__DFFS_NP0_), ID($__DFFS_NP1_),
+ ID($__DFFS_PN0_), ID($__DFFS_PN1_), ID($__DFFS_PP0_), ID($__DFFS_PP1_),
+ ID($__DFFSE_NN0), ID($__DFFSE_NN1), ID($__DFFSE_NP0), ID($__DFFSE_NP1),
+ ID($__DFFSE_PN0), ID($__DFFSE_PN1), ID($__DFFSE_PP0), ID($__DFFSE_PP1)
};
for (auto cell : module->selected_cells())
@@ -113,8 +122,10 @@ struct ZinitPass : public Pass {
for (int i = 0; i < GetSize(sig_q); i++) {
if (initbits.count(sig_q[i])) {
- initval.bits.push_back(initbits.at(sig_q[i]));
- donebits.insert(sig_q[i]);
+ const auto &d = initbits.at(sig_q[i]);
+ initval.bits.push_back(d.first);
+ const auto &b = d.second;
+ b.wire->attributes.at(ID::init)[b.offset] = State::Sx;
} else
initval.bits.push_back(all_mode ? State::S0 : State::Sx);
}
@@ -123,11 +134,11 @@ struct ZinitPass : public Pass {
initwire->attributes[ID::init] = initval;
for (int i = 0; i < GetSize(initwire); i++)
- if (initval.bits.at(i) == State::S1)
+ if (initval[i] == State::S1)
{
sig_d[i] = module->NotGate(NEW_ID, sig_d[i]);
module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]);
- initwire->attributes[ID::init].bits.at(i) = State::S0;
+ initwire->attributes[ID::init][i] = State::S0;
}
else
{
@@ -139,11 +150,36 @@ struct ZinitPass : public Pass {
cell->setPort(ID::D, sig_d);
cell->setPort(ID::Q, initwire);
- }
- for (auto &it : initbits)
- if (donebits.count(it.first) == 0)
- log_error("Failed to handle init bit %s = %s.\n", log_signal(it.first), log_signal(it.second));
+ if (cell->type == ID($adff)) {
+ 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 (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($__DFFE_NN0), ID($__DFFE_NN1), ID($__DFFE_NP0), ID($__DFFE_NP1),
+ ID($__DFFE_PN0), ID($__DFFE_PN1), ID($__DFFE_PP0), ID($__DFFE_PP1),
+ ID($__DFFS_NN0_), ID($__DFFS_NN1_), ID($__DFFS_NP0_), ID($__DFFS_NP1_),
+ ID($__DFFS_PN0_), ID($__DFFS_PN1_), ID($__DFFS_PP0_), ID($__DFFS_PP1_)))
+ {
+ t[10] = (t[10] == '0' ? '1' : '0');
+ }
+ else if (cell->type.in(ID($__DFFSE_NN0), ID($__DFFSE_NN1), ID($__DFFSE_NP0), ID($__DFFSE_NP1),
+ ID($__DFFSE_PN0), ID($__DFFSE_PN1), ID($__DFFSE_PP0), ID($__DFFSE_PP1)))
+ {
+ t[11] = (t[11] == '0' ? '1' : '0');
+ }
+ cell->type = t;
+ }
+ }
}
}
} ZinitPass;