aboutsummaryrefslogtreecommitdiffstats
path: root/passes/techmap/clkbufmap.cc
diff options
context:
space:
mode:
authorMarcin Koƛcielnicki <koriakin@0x04.net>2019-11-24 16:05:45 +0100
committerMarcin Koƛcielnicki <mwk@0x04.net>2019-11-25 20:40:39 +0100
commit6cdea425b81fcfe1eec20cbfc4c4e27d46cb641d (patch)
tree479662c910620126719f95acbd2ab7893496e1ed /passes/techmap/clkbufmap.cc
parent7562e7304e2592ddd5a914ec723a6563c14141e0 (diff)
downloadyosys-6cdea425b81fcfe1eec20cbfc4c4e27d46cb641d.tar.gz
yosys-6cdea425b81fcfe1eec20cbfc4c4e27d46cb641d.tar.bz2
yosys-6cdea425b81fcfe1eec20cbfc4c4e27d46cb641d.zip
clkbufmap: Add support for inverters in clock path.
Diffstat (limited to 'passes/techmap/clkbufmap.cc')
-rw-r--r--passes/techmap/clkbufmap.cc41
1 files changed, 41 insertions, 0 deletions
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())