diff options
Diffstat (limited to 'passes/techmap/zinit.cc')
-rw-r--r-- | passes/techmap/zinit.cc | 64 |
1 files changed, 40 insertions, 24 deletions
diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc index ac3d4ed4a..9eb47ff6d 100644 --- a/passes/techmap/zinit.cc +++ b/passes/techmap/zinit.cc @@ -57,17 +57,15 @@ 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()) { - if (wire->attributes.count(ID(init)) == 0) + if (wire->attributes.count(ID::init) == 0) continue; SigSpec wirebits = sigmap(wire); - Const initval = wire->attributes.at(ID(init)); - wire->attributes.erase(ID(init)); + Const initval = wire->attributes.at(ID::init); for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) { @@ -78,22 +76,25 @@ 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_) }; @@ -103,8 +104,8 @@ struct ZinitPass : public Pass { if (!dff_types.count(cell->type)) continue; - SigSpec sig_d = sigmap(cell->getPort(ID(D))); - SigSpec sig_q = sigmap(cell->getPort(ID(Q))); + 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) continue; @@ -113,21 +114,23 @@ 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); } Wire *initwire = module->addWire(NEW_ID, GetSize(initval)); - initwire->attributes[ID(init)] = initval; + 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 { @@ -137,13 +140,26 @@ struct ZinitPass : public Pass { 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); - } + 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 (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_))) + { + if (initval == State::S1) { + std::string t = cell->type.str(); + t[8] = (t[8] == '0' ? '1' : '0'); + cell->type = t; + } + } + } } } } ZinitPass; |