3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-13 04:28:18 +00:00

abc9_ops -prep_dff: insert async s/r mux in holes when replacing $_DFF_*

This commit is contained in:
Eddie Hung 2020-01-23 14:58:56 -08:00
parent af0e7637a2
commit 1d4314d888

View file

@ -106,38 +106,44 @@ void prep_dff(RTLIL::Module *module)
SigMap sigmap(holes_module); SigMap sigmap(holes_module);
dict<SigSpec, SigSpec> replace; dict<SigSpec, SigSpec> replace;
for (auto it = holes_module->cells_.begin(); it != holes_module->cells_.end(); ) { for (auto cell : holes_module->cells().to_vector()) {
auto cell = it->second; if (!cell->type.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
if (cell->type.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", "$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_"))
"$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_")) { continue;
SigBit D = cell->getPort("\\D"); SigBit D = cell->getPort("\\D");
SigBit Q = cell->getPort("\\Q"); SigBit Q = cell->getPort("\\Q");
// Remove the $_DFF_* cell from what needs to be a combinatorial box // Emulate async control embedded inside $_DFF_* cell with mux in front of D
it = holes_module->cells_.erase(it); if (cell->type.in("$_DFF_NN0_", "$_DFF_PN0_"))
Wire *port; D = holes_module->MuxGate(NEW_ID, State::S0, D, cell->getPort("\\R"));
if (GetSize(Q.wire) == 1) else if (cell->type.in("$_DFF_NN1_", "$_DFF_PN1_"))
port = holes_module->wire(stringf("$abc%s", Q.wire->name.c_str())); D = holes_module->MuxGate(NEW_ID, State::S1, D, cell->getPort("\\R"));
else else if (cell->type.in("$_DFF_NP0_", "$_DFF_PP0_"))
port = holes_module->wire(stringf("$abc%s[%d]", Q.wire->name.c_str(), Q.offset)); D = holes_module->MuxGate(NEW_ID, D, State::S0, cell->getPort("\\R"));
log_assert(port); else if (cell->type.in("$_DFF_NP1_", "$_DFF_PP1_"))
// Prepare to replace "assign <port> = $_DFF_*.Q;" with "assign <port> = $_DFF_*.D;" D = holes_module->MuxGate(NEW_ID, D, State::S1, cell->getPort("\\R"));
// in order to extract just the combinatorial control logic that feeds the box // Remove the $_DFF_* cell from what needs to be a combinatorial box
// (i.e. clock enable, synchronous reset, etc.) holes_module->remove(cell);
replace.insert(std::make_pair(Q,D)); Wire *port;
// Since `flatten` above would have created wires named "<cell>.Q", if (GetSize(Q.wire) == 1)
// extract the pre-techmap cell name port = holes_module->wire(stringf("$abc%s", Q.wire->name.c_str()));
auto pos = Q.wire->name.str().rfind(".");
log_assert(pos != std::string::npos);
IdString driver = Q.wire->name.substr(0, pos);
// And drive the signal that was previously driven by "DFF.Q" (typically
// used to implement clock-enable functionality) with the "<cell>.$abc9_currQ"
// wire (which itself is driven an by input port) we inserted above
Wire *currQ = holes_module->wire(stringf("%s.abc9_ff.Q", driver.c_str()));
log_assert(currQ);
holes_module->connect(Q, currQ);
}
else else
++it; port = holes_module->wire(stringf("$abc%s[%d]", Q.wire->name.c_str(), Q.offset));
log_assert(port);
// Prepare to replace "assign <port> = $_DFF_*.Q;" with "assign <port> = $_DFF_*.D;"
// in order to extract just the combinatorial control logic that feeds the box
// (i.e. clock enable, synchronous reset, etc.)
replace.insert(std::make_pair(Q,D));
// Since `flatten` above would have created wires named "<cell>.Q",
// extract the pre-techmap cell name
auto pos = Q.wire->name.str().rfind(".");
log_assert(pos != std::string::npos);
IdString driver = Q.wire->name.substr(0, pos);
// And drive the signal that was previously driven by "DFF.Q" (typically
// used to implement clock-enable functionality) with the "<cell>.$abc9_currQ"
// wire (which itself is driven an by input port) we inserted above
Wire *currQ = holes_module->wire(stringf("%s.abc9_ff.Q", driver.c_str()));
log_assert(currQ);
holes_module->connect(Q, currQ);
} }
for (auto &conn : holes_module->connections_) for (auto &conn : holes_module->connections_)