aboutsummaryrefslogtreecommitdiffstats
path: root/passes/techmap
diff options
context:
space:
mode:
Diffstat (limited to 'passes/techmap')
-rw-r--r--passes/techmap/abc9.cc69
-rw-r--r--passes/techmap/clkbufmap.cc41
2 files changed, 81 insertions, 29 deletions
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 27106cc5d..8276c3c16 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -94,20 +94,30 @@ void handle_loops(RTLIL::Design *design)
if (cell->output(c.first)) {
SigBit b = c.second.as_bit();
Wire *w = b.wire;
- log_assert(!w->port_input);
- w->port_input = true;
- w = module->wire(stringf("%s.abci", w->name.c_str()));
- if (!w) {
- w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire));
- w->port_output = true;
+ if (w->port_input) {
+ // In this case, hopefully the loop break has been already created
+ // Get the non-prefixed wire
+ Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str()));
+ log_assert(wo != nullptr);
+ log_assert(wo->port_output);
+ log_assert(b.offset < GetSize(wo));
+ c.second = RTLIL::SigBit(wo, b.offset);
}
else {
- log_assert(w->port_input);
- log_assert(b.offset < GetSize(w));
+ // Create a new output/input loop break
+ w->port_input = true;
+ w = module->wire(stringf("%s.abco", w->name.c_str()));
+ if (!w) {
+ w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire));
+ w->port_output = true;
+ }
+ else {
+ log_assert(w->port_input);
+ log_assert(b.offset < GetSize(w));
+ }
+ w->set_bool_attribute(ID(abc9_scc_break));
+ c.second = RTLIL::SigBit(w, b.offset);
}
- w->set_bool_attribute(ID(abc9_scc_break));
- module->swap_names(b.wire, w);
- c.second = RTLIL::SigBit(w, b.offset);
}
}
}
@@ -420,24 +430,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
design->selection_stack.pop_back();
- // Now 'unexpose' those wires by undoing
- // the expose operation -- remove them from PO/PI
- // and re-connecting them back together
- for (auto wire : module->wires()) {
- auto it = wire->attributes.find(ID(abc9_scc_break));
- if (it != wire->attributes.end()) {
- wire->attributes.erase(it);
- log_assert(wire->port_output);
- wire->port_output = false;
- RTLIL::Wire *i_wire = module->wire(wire->name.str() + ".abci");
- log_assert(i_wire);
- log_assert(i_wire->port_input);
- i_wire->port_input = false;
- module->connect(i_wire, wire);
- }
- }
- module->fixup_ports();
-
log_header(design, "Executing ABC9.\n");
if (!lut_costs.empty()) {
@@ -781,6 +773,25 @@ clone_lut:
}
}
+ // Now 'unexpose' those wires by undoing
+ // the expose operation -- remove them from PO/PI
+ // and re-connecting them back together
+ for (auto wire : module->wires()) {
+ auto it = wire->attributes.find(ID(abc9_scc_break));
+ if (it != wire->attributes.end()) {
+ wire->attributes.erase(it);
+ log_assert(wire->port_output);
+ wire->port_output = false;
+ std::string name = wire->name.str();
+ RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5));
+ log_assert(i_wire);
+ log_assert(i_wire->port_input);
+ i_wire->port_input = false;
+ module->connect(i_wire, wire);
+ }
+ }
+ module->fixup_ports();
+
//log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires);
log("ABC RESULTS: input signals: %8d\n", in_wires);
log("ABC RESULTS: output signals: %8d\n", out_wires);
diff --git a/passes/techmap/clkbufmap.cc b/passes/techmap/clkbufmap.cc
index 246932d81..b9cd68883 100644
--- a/passes/techmap/clkbufmap.cc
+++ b/passes/techmap/clkbufmap.cc
@@ -115,6 +115,8 @@ struct ClkbufmapPass : public Pass {
// Cell type, port name, bit index.
pool<pair<IdString, pair<IdString, int>>> sink_ports;
pool<pair<IdString, pair<IdString, int>>> buf_ports;
+ dict<pair<IdString, pair<IdString, int>>, pair<IdString, int>> inv_ports_out;
+ dict<pair<IdString, pair<IdString, int>>, pair<IdString, int>> inv_ports_in;
// Process submodules before module using them.
std::vector<Module *> modules_sorted;
@@ -133,6 +135,14 @@ struct ClkbufmapPass : public Pass {
if (wire->get_bool_attribute("\\clkbuf_sink"))
for (int i = 0; i < GetSize(wire); i++)
sink_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
+ auto it = wire->attributes.find("\\clkbuf_inv");
+ if (it != wire->attributes.end()) {
+ IdString in_name = RTLIL::escape_id(it->second.decode_string());
+ for (int i = 0; i < GetSize(wire); i++) {
+ inv_ports_out[make_pair(module->name, make_pair(wire->name, i))] = make_pair(in_name, i);
+ inv_ports_in[make_pair(module->name, make_pair(in_name, i))] = make_pair(wire->name, i);
+ }
+ }
}
continue;
}
@@ -157,6 +167,37 @@ struct ClkbufmapPass : public Pass {
if (buf_ports.count(make_pair(cell->type, make_pair(port.first, i))))
buf_wire_bits.insert(sigmap(port.second[i]));
+ // Third, propagate tags through inverters.
+ bool retry = true;
+ while (retry) {
+ retry = false;
+ for (auto cell : module->cells())
+ for (auto port : cell->connections())
+ for (int i = 0; i < port.second.size(); i++) {
+ auto it = inv_ports_out.find(make_pair(cell->type, make_pair(port.first, i)));
+ auto bit = sigmap(port.second[i]);
+ // If output of an inverter is connected to a sink, mark it as buffered,
+ // and request a buffer on the inverter's input instead.
+ if (it != inv_ports_out.end() && !buf_wire_bits.count(bit) && sink_wire_bits.count(bit)) {
+ buf_wire_bits.insert(bit);
+ auto other_bit = sigmap(cell->getPort(it->second.first)[it->second.second]);
+ sink_wire_bits.insert(other_bit);
+ retry = true;
+ }
+ // If input of an inverter is marked as already-buffered,
+ // mark its output already-buffered as well.
+ auto it2 = inv_ports_in.find(make_pair(cell->type, make_pair(port.first, i)));
+ if (it2 != inv_ports_in.end() && buf_wire_bits.count(bit)) {
+ auto other_bit = sigmap(cell->getPort(it2->second.first)[it2->second.second]);
+ if (!buf_wire_bits.count(other_bit)) {
+ buf_wire_bits.insert(other_bit);
+ retry = true;
+ }
+ }
+
+ }
+ };
+
// Collect all driven bits.
for (auto cell : module->cells())
for (auto port : cell->connections())