From ddbe81df78df93d2608ca0280c3a3a60b06f8215 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Feb 2020 18:00:07 -0800 Subject: [PATCH] timinginfo: arrival/required times with clocks --- backends/aiger/xaiger.cc | 30 ++++++++++++-------------- kernel/timinginfo.h | 44 +++++++++++++++++++------------------- passes/cmds/sta.cc | 18 +++++++--------- passes/techmap/abc9_ops.cc | 37 ++++++++++++++++---------------- 4 files changed, 63 insertions(+), 66 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1fb7210cb..a29b9e694 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -255,26 +255,24 @@ struct XAigerWriter if (!timing.count(derived_type)) timing.setup_module(inst_module); - auto &t = timing.at(derived_type).arrival; - for (const auto &conn : cell->connections()) { - auto port_wire = inst_module->wire(conn.first); - if (!port_wire->port_output) - continue; - for (int i = 0; i < GetSize(conn.second); i++) { - auto d = t.at(TimingInfo::NameBit(conn.first,i), 0); - if (d == 0) - continue; + for (auto &i : timing.at(derived_type).arrival) { + auto port_wire = inst_module->wire(i.first.name); + log_assert(port_wire->port_output); + + auto d = i.second.first; + if (d == 0) + continue; + auto offset = i.first.offset; #ifndef NDEBUG - if (ys_debug(1)) { - static std::set> seen; - if (seen.emplace(derived_type, conn.first, i).second) log("%s.%s[%d] abc9_arrival = %d\n", - log_id(cell->type), log_id(conn.first), i, d); - } -#endif - arrival_times[conn.second[i]] = d; + if (ys_debug(1)) { + static std::set> seen; + if (seen.emplace(derived_type, i.first).second) log("%s.%s[%d] abc9_arrival = %d\n", + log_id(cell->type), log_id(i.first.name), offset, d); } +#endif + arrival_times[cell->getPort(i.first.name)[offset]] = d; } if (abc9_flop) diff --git a/kernel/timinginfo.h b/kernel/timinginfo.h index fb4e0930d..c08cc47b2 100644 --- a/kernel/timinginfo.h +++ b/kernel/timinginfo.h @@ -36,6 +36,7 @@ struct TimingInfo explicit NameBit(const RTLIL::SigBit &b) : name(b.wire->name), offset(b.offset) {} bool operator==(const NameBit& nb) const { return nb.name == name && nb.offset == offset; } bool operator!=(const NameBit& nb) const { return !operator==(nb); } + bool operator<(const NameBit& nb) const { return nb.name < name && nb.offset < offset; } unsigned int hash() const { return mkhash_add(name.hash(), offset); } }; struct BitBit @@ -49,9 +50,8 @@ struct TimingInfo struct ModuleTiming { - RTLIL::IdString type; dict comb; - dict arrival, required; + dict> arrival, required; }; dict data; @@ -117,26 +117,26 @@ struct TimingInfo } } else if (cell->type == ID($specify3)) { - auto src = cell->getPort(ID::SRC); + auto src = cell->getPort(ID::SRC).as_bit(); auto dst = cell->getPort(ID::DST); - for (const auto &c : src.chunks()) - if (!c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); + if (!src.wire->port_input) + log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); for (const auto &c : dst.chunks()) if (!c.wire->port_output) log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); int max = std::max(rise_max,fall_max); - if (max < 0) - log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - if (max <= 0) { - log_debug("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - continue; + if (max < 0) { + log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported; clamping to zero .\n", log_id(module), log_id(cell)); + max = 0; } for (const auto &d : dst) { auto &v = t.arrival[NameBit(d)]; - v = std::max(v, max); + if (v.first < max) { + v.first = max; + v.second = NameBit(src); + } } } else if (cell->type == ID($specrule)) { @@ -144,23 +144,23 @@ struct TimingInfo if (type != "$setup" && type != "$setuphold") continue; auto src = cell->getPort(ID::SRC); - auto dst = cell->getPort(ID::DST); + auto dst = cell->getPort(ID::DST).as_bit(); for (const auto &c : src.chunks()) if (!c.wire->port_input) log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); - for (const auto &c : dst.chunks()) - if (!c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); + if (!dst.wire->port_input) + log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); int max = cell->getParam(ID::T_LIMIT_MAX).as_int(); - if (max < 0) - log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - if (max <= 0) { - log_debug("Module '%s' contains specify cell '%s' with T_LIMIT_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - continue; + if (max < 0) { + log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported; clamping to zero.\n", log_id(module), log_id(cell)); + max = 0; } for (const auto &s : src) { auto &v = t.required[NameBit(s)]; - v = std::max(v, max); + if (v.first < max) { + v.first = max; + v.second = NameBit(dst); + } } } } diff --git a/passes/cmds/sta.cc b/passes/cmds/sta.cc index 71d9d4061..79749f114 100644 --- a/passes/cmds/sta.cc +++ b/passes/cmds/sta.cc @@ -82,7 +82,7 @@ struct StaWorker auto it = t.required.find(namebit); if (it == t.required.end()) continue; - endpoints[bit] = it->second; + endpoints[bit] = it->second.first; } if (cell->output(conn.first)) { dst_bits.insert(std::make_pair(bit,namebit)); @@ -90,14 +90,8 @@ struct StaWorker auto it = t.arrival.find(namebit); if (it == t.arrival.end()) continue; - auto arrivals = bit.wire->get_intvec_attribute(ID(sta_arrival)); - if (arrivals.empty()) - arrivals = std::vector(GetSize(bit.wire), -1); - else - log_assert(GetSize(arrivals) == GetSize(bit.wire)); - arrivals[bit.offset] = it->second; - bit.wire->set_intvec_attribute(ID(sta_arrival), arrivals); - queue.emplace_back(bit); + const auto &s = it->second.second; + fanouts[cell->getPort(s.name)[s.offset]].emplace_back(bit,it->second.first); } } } @@ -143,7 +137,7 @@ struct StaWorker auto new_arrival = src_arrival + d.second + endpoints.at(d.first, 0); if (dst_arrival < new_arrival) { dst_arrival = std::max(dst_arrival, new_arrival); - if (dst_arrival > maxarrival) { + if (endpoints.count(d.first) && dst_arrival > maxarrival) { maxarrival = dst_arrival; maxbit = d.first; } @@ -169,6 +163,10 @@ struct StaWorker std::map arrival_histogram; for (const auto &i : endpoints) { const auto &b = i.first; + if (!b.wire->attributes.count(ID(sta_arrival))) { + log_warning("Wire %s.%s has no (* sta_arrival *) value.\n", log_id(module), log_signal(b)); + continue; + } auto arrival = b.wire->get_intvec_attribute(ID(sta_arrival))[b.offset]; arrival += i.second; arrival_histogram[arrival]++; diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 1345188a4..5e847aeda 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -440,25 +440,26 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) if (!port_wire->port_input) continue; - SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); - for (int i = 0; i < GetSize(conn.second); i++) { - auto d = t.at(TimingInfo::NameBit(conn.first,i), 0); - if (d == 0) - continue; + auto d = i.second.first; + if (d == 0) + continue; + auto offset = i.first.offset; + auto O = module->addWire(NEW_ID); + auto rhs = cell->getPort(i.first.name); #ifndef NDEBUG - if (ys_debug(1)) { - static std::set> seen; - if (seen.emplace(derived_type, conn.first, i).second) log("%s.%s[%d] abc9_required = %d\n", - log_id(cell->type), log_id(conn.first), i, d); - } -#endif - auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); - box->setPort(ID::I, conn.second[i]); - box->setPort(ID::O, O[i]); - box->setParam(ID::DELAY, d); - conn.second[i] = O[i]; + if (ys_debug(1)) { + static std::set> seen; + if (seen.emplace(derived_type, i.first).second) log("%s.%s[%d] abc9_required = %d\n", + log_id(cell->type), log_id(i.first.name), offset, d); } +#endif + auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); + box->setPort(ID::I, rhs[offset]); + box->setPort(ID::O, O); + box->setParam(ID::DELAY, d); + rhs[offset] = O; + cell->setPort(i.first.name, rhs); } } } @@ -606,13 +607,13 @@ void prep_box(RTLIL::Design *design, bool dff_mode) // Assume that no setup time means zero ss << 0; else { - ss << it->second; + ss << it->second.first; #ifndef NDEBUG if (ys_debug(1)) { static std::set> seen; if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module), - log_id(port_name), it->second); + log_id(port_name), it->second.first); } #endif }