From 1d4314d88853feb1fa6af13fe56274d53d81d853 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 23 Jan 2020 14:58:56 -0800 Subject: abc9_ops -prep_dff: insert async s/r mux in holes when replacing $_DFF_* --- passes/techmap/abc9_ops.cc | 68 +++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 31 deletions(-) (limited to 'passes/techmap/abc9_ops.cc') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 5091ac0f2..750f36ceb 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -106,38 +106,44 @@ void prep_dff(RTLIL::Module *module) SigMap sigmap(holes_module); dict replace; - for (auto it = holes_module->cells_.begin(); it != holes_module->cells_.end(); ) { - auto cell = it->second; - if (cell->type.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", - "$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_")) { - SigBit D = cell->getPort("\\D"); - SigBit Q = cell->getPort("\\Q"); - // Remove the $_DFF_* cell from what needs to be a combinatorial box - it = holes_module->cells_.erase(it); - Wire *port; - if (GetSize(Q.wire) == 1) - port = holes_module->wire(stringf("$abc%s", Q.wire->name.c_str())); - else - port = holes_module->wire(stringf("$abc%s[%d]", Q.wire->name.c_str(), Q.offset)); - log_assert(port); - // Prepare to replace "assign = $_DFF_*.Q;" with "assign = $_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 ".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 ".$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 cell : holes_module->cells().to_vector()) { + if (!cell->type.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", + "$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_")) + continue; + SigBit D = cell->getPort("\\D"); + SigBit Q = cell->getPort("\\Q"); + // Emulate async control embedded inside $_DFF_* cell with mux in front of D + if (cell->type.in("$_DFF_NN0_", "$_DFF_PN0_")) + D = holes_module->MuxGate(NEW_ID, State::S0, D, cell->getPort("\\R")); + else if (cell->type.in("$_DFF_NN1_", "$_DFF_PN1_")) + D = holes_module->MuxGate(NEW_ID, State::S1, D, cell->getPort("\\R")); + else if (cell->type.in("$_DFF_NP0_", "$_DFF_PP0_")) + D = holes_module->MuxGate(NEW_ID, D, State::S0, cell->getPort("\\R")); + else if (cell->type.in("$_DFF_NP1_", "$_DFF_PP1_")) + D = holes_module->MuxGate(NEW_ID, D, State::S1, cell->getPort("\\R")); + // Remove the $_DFF_* cell from what needs to be a combinatorial box + holes_module->remove(cell); + Wire *port; + if (GetSize(Q.wire) == 1) + port = holes_module->wire(stringf("$abc%s", Q.wire->name.c_str())); else - ++it; + port = holes_module->wire(stringf("$abc%s[%d]", Q.wire->name.c_str(), Q.offset)); + log_assert(port); + // Prepare to replace "assign = $_DFF_*.Q;" with "assign = $_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 ".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 ".$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_) -- cgit v1.2.3 From f180dba753c9f4bfb3b89575b0d224c73a1e8897 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 23 Jan 2020 18:56:06 -0800 Subject: abc9_ops: -prep_xaiger to skip (* keep *) cells --- passes/techmap/abc9_ops.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'passes/techmap/abc9_ops.cc') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 750f36ceb..40622ece7 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -165,6 +165,8 @@ void prep_xaiger(RTLIL::Module *module, bool dff) for (auto cell : module->cells()) { if (cell->type == "$__ABC9_FF_") continue; + if (cell->has_keep_attr()) + continue; auto inst_module = module->design->module(cell->type); bool abc9_box = inst_module && inst_module->attributes.count("\\abc9_box_id"); -- cgit v1.2.3 From dbf351390e68a9d7c453e893de8fa9d09eb24f62 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 23 Jan 2020 22:45:34 -0800 Subject: abc9: -reintegrate recover type from existing cell, check against boxid --- passes/techmap/abc9_ops.cc | 49 ++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 30 deletions(-) (limited to 'passes/techmap/abc9_ops.cc') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 40622ece7..d238ce0ad 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -356,24 +356,14 @@ void reintegrate(RTLIL::Module *module) for (auto w : mapped_mod->wires()) module->addWire(remap_name(w->name), GetSize(w)); - dict box_lookup; dict> box_ports; for (auto m : design->modules()) { - auto it = m->attributes.find(ID(abc9_box_id)); - if (it == m->attributes.end()) + if (!m->attributes.count(ID(abc9_box_id))) continue; - if (m->name.begins_with("$paramod")) - continue; - auto id = it->second.as_int(); - auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); - if (!r.second) - log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", - log_id(m), id, log_id(r.first->second)); - log_assert(r.second); - auto r2 = box_ports.insert(m->name); - if (r2.second) { + auto r = box_ports.insert(m->name); + if (r.second) { // Make carry in the last PI, and carry out the last PO // since ABC requires it this way IdString carry_in, carry_out; @@ -393,7 +383,7 @@ void reintegrate(RTLIL::Module *module) } } else - r2.first->second.push_back(port_name); + r.first->second.push_back(port_name); } if (carry_in != IdString() && carry_out == IdString()) @@ -401,8 +391,8 @@ void reintegrate(RTLIL::Module *module) if (carry_in == IdString() && carry_out != IdString()) log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); if (carry_in != IdString()) { - r2.first->second.push_back(carry_in); - r2.first->second.push_back(carry_out); + r.first->second.push_back(carry_in); + r.first->second.push_back(carry_out); } } } @@ -516,28 +506,27 @@ void reintegrate(RTLIL::Module *module) else { RTLIL::Cell *existing_cell = module->cell(mapped_cell->name); log_assert(existing_cell); - log_assert(mapped_cell->type.begins_with("$__boxid")); - auto type = box_lookup.at(mapped_cell->type, IdString()); - if (type == IdString()) - log_error("No module with abc9_box_id = %s found.\n", mapped_cell->type.c_str() + strlen("$__boxid")); - mapped_cell->type = type; + RTLIL::Module* box_module = design->module(existing_cell->type); + auto it = box_module->attributes.find(ID(abc9_box_id)); + log_assert(it != box_module->attributes.end()); + log_assert(mapped_cell->type == stringf("$__boxid%d", it->second.as_int())); + mapped_cell->type = existing_cell->type; RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type); cell->parameters = existing_cell->parameters; cell->attributes = existing_cell->attributes; module->swap_names(cell, existing_cell); - auto it = mapped_cell->connections_.find("\\i"); - log_assert(it != mapped_cell->connections_.end()); - SigSpec inputs = std::move(it->second); - mapped_cell->connections_.erase(it); - it = mapped_cell->connections_.find("\\o"); - log_assert(it != mapped_cell->connections_.end()); - SigSpec outputs = std::move(it->second); - mapped_cell->connections_.erase(it); + auto jt = mapped_cell->connections_.find("\\i"); + log_assert(jt != mapped_cell->connections_.end()); + SigSpec inputs = std::move(jt->second); + mapped_cell->connections_.erase(jt); + jt = mapped_cell->connections_.find("\\o"); + log_assert(jt != mapped_cell->connections_.end()); + SigSpec outputs = std::move(jt->second); + mapped_cell->connections_.erase(jt); - RTLIL::Module* box_module = design->module(mapped_cell->type); auto abc9_flop = box_module->attributes.count("\\abc9_flop"); if (!abc9_flop) { for (const auto &i : inputs) -- cgit v1.2.3 From 9009b76a69b9e867f69295a8e555305925e83aeb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 Jan 2020 11:18:21 -0800 Subject: abc9_ops: add comments --- passes/techmap/abc9_ops.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'passes/techmap/abc9_ops.cc') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index d238ce0ad..9ad29a8f6 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -213,6 +213,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) else if (!yosys_celltypes.cell_known(cell->type)) continue; + // TODO: Speed up toposort -- we care about box ordering only for (auto conn : cell->connections()) { if (cell->input(conn.first)) for (auto bit : sigmap(conn.second)) @@ -222,7 +223,6 @@ void prep_xaiger(RTLIL::Module *module, bool dff) for (auto bit : sigmap(conn.second)) bit_drivers[bit].insert(cell->name); } - toposort.node(cell->name); } @@ -415,6 +415,7 @@ void reintegrate(RTLIL::Module *module) std::map cell_stats; for (auto mapped_cell : mapped_mod->cells()) { + // TODO: Speed up toposort -- we care about NOT ordering only toposort.node(mapped_cell->name); if (mapped_cell->type == ID($_NOT_)) { @@ -625,6 +626,17 @@ void reintegrate(RTLIL::Module *module) } } + // ABC9 will return $_NOT_ gates in its mapping (since they are + // treated as being "free"), in particular driving primary + // outputs (real primary outputs, or cells treated as blackboxes) + // or driving box inputs. + // Instead of just mapping those $_NOT_ gates into 2-input $lut-s + // at an area and delay cost, see if it is possible to push + // this $_NOT_ into the driving LUT, or into all sink LUTs. + // When this is not possible, (i.e. this signal drives two primary + // outputs, only one of which is complemented) and when the driver + // is a LUT, then clone the LUT so that it can be inverted without + // increasing depth/delay. for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) -- cgit v1.2.3