From 92a92abd567d3d5b97147bc98e2317cc042d6796 Mon Sep 17 00:00:00 2001 From: Rowan Goemans Date: Mon, 23 Sep 2024 16:12:23 +0200 Subject: [PATCH] common: Move CellPortKey to nextpnr_types.h --- common/kernel/nextpnr_types.h | 21 +++++++++ common/kernel/timing.cc | 36 +++++++-------- common/kernel/timing.h | 82 +++++------------------------------ 3 files changed, 49 insertions(+), 90 deletions(-) diff --git a/common/kernel/nextpnr_types.h b/common/kernel/nextpnr_types.h index e23cd16a..3abdb81f 100644 --- a/common/kernel/nextpnr_types.h +++ b/common/kernel/nextpnr_types.h @@ -369,6 +369,27 @@ struct CellInfo : ArchCellInfo int new_offset, bool new_brackets, int width); }; +// similar to PortRef but allows storage into pool and dict +struct CellPortKey +{ + CellPortKey(){}; + CellPortKey(IdString cell, IdString port) : cell(cell), port(port){}; + explicit CellPortKey(const PortRef &pr) + { + NPNR_ASSERT(pr.cell != nullptr); + cell = pr.cell->name; + port = pr.port; + } + IdString cell, port; + unsigned int hash() const { return mkhash(cell.hash(), port.hash()); } + inline bool operator==(const CellPortKey &other) const { return (cell == other.cell) && (port == other.port); } + inline bool operator!=(const CellPortKey &other) const { return (cell != other.cell) || (port != other.port); } + inline bool operator<(const CellPortKey &other) const + { + return cell == other.cell ? port < other.port : cell < other.cell; + } +}; + struct ClockConstraint { DelayPair high; diff --git a/common/kernel/timing.cc b/common/kernel/timing.cc index 2cc7cd63..9d370263 100644 --- a/common/kernel/timing.cc +++ b/common/kernel/timing.cc @@ -262,13 +262,13 @@ void TimingAnalyser::setup_port_domains_and_constraints() // copy domains across routing if (pi.net != nullptr) for (auto &usr : pi.net->users) - copy_domains(port, CellPortKey(usr), false); + propagate_domains_and_constraints(port, CellPortKey(usr), false); } else { // copy domains from input to output for (auto &fanout : pd.cell_arcs) { if (fanout.type != CellArc::COMBINATIONAL) continue; - copy_domains(port, CellPortKey(port.cell, fanout.other_port), false); + propagate_domains_and_constraints(port, CellPortKey(port.cell, fanout.other_port), false); } } } @@ -281,7 +281,7 @@ void TimingAnalyser::setup_port_domains_and_constraints() for (auto &fanin : pd.cell_arcs) { if (fanin.type != CellArc::COMBINATIONAL) continue; - copy_domains(port, CellPortKey(port.cell, fanin.other_port), true); + propagate_domains_and_constraints(port, CellPortKey(port.cell, fanin.other_port), true); } } else { if (first_iter) { @@ -302,7 +302,7 @@ void TimingAnalyser::setup_port_domains_and_constraints() } // copy port to driver if (pi.net != nullptr && pi.net->driver.cell != nullptr) - copy_domains(port, CellPortKey(pi.net->driver), true); + propagate_domains_and_constraints(port, CellPortKey(pi.net->driver), true); } } // Iterate over ports and find domain pairs @@ -1296,29 +1296,25 @@ domain_id_t TimingAnalyser::domain_pair_id(domain_id_t launch, domain_id_t captu return inserted.first->second; } -void TimingAnalyser::copy_domains(const CellPortKey &from, const CellPortKey &to, bool backward) +void TimingAnalyser::propagate_domains_and_constraints(const CellPortKey &from, const CellPortKey &to, bool backward) { auto &f = ports.at(from), &t = ports.at(to); for (auto &dom : (backward ? f.required : f.arrival)) { updated_domains_constraints |= (backward ? t.required : t.arrival).emplace(dom.first, ArrivReqTime{}).second; } -} -void TimingAnalyser::propagate_constraints(const CellPortKey &from, const CellPortKey &to, bool backward) -{ - auto &f = ports.at(from), &t = ports.at(to); - for (auto &ct : f.per_constraint) { - bool has_constraint = t.per_constraint.count(ct.first) > 0; - bool same_constraint = has_constraint ? ct.second == t.per_constraint.at(ct.first) : false; + // for (auto &ct : f.per_constraint) { + // bool has_constraint = t.per_constraint.count(ct.first) > 0; + // bool same_constraint = has_constraint ? ct.second == t.per_constraint.at(ct.first) : false; - if (t.per_constraint.count(ct.first) > 0) { - if (backward) { - t.per_constraint[ct.first] = CONSTRAINED; - } - } else if (!backward) { - t.per_constraint[ct.first] = FORWARDONLY; - } - } + // if (t.per_constraint.count(ct.first) > 0) { + // if (backward) { + // t.per_constraint[ct.first] = CONSTRAINED; + // } + // } else if (!backward) { + // t.per_constraint[ct.first] = FORWARDONLY; + // } + // } } const std::string TimingAnalyser::arcType_to_str(CellArc::ArcType typ) diff --git a/common/kernel/timing.h b/common/kernel/timing.h index 1915f9ec..c1f4469c 100644 --- a/common/kernel/timing.h +++ b/common/kernel/timing.h @@ -25,26 +25,6 @@ NEXTPNR_NAMESPACE_BEGIN -struct CellPortKey -{ - CellPortKey(){}; - CellPortKey(IdString cell, IdString port) : cell(cell), port(port){}; - explicit CellPortKey(const PortRef &pr) - { - NPNR_ASSERT(pr.cell != nullptr); - cell = pr.cell->name; - port = pr.port; - } - IdString cell, port; - unsigned int hash() const { return mkhash(cell.hash(), port.hash()); } - inline bool operator==(const CellPortKey &other) const { return (cell == other.cell) && (port == other.port); } - inline bool operator!=(const CellPortKey &other) const { return (cell != other.cell) || (port != other.port); } - inline bool operator<(const CellPortKey &other) const - { - return cell == other.cell ? port < other.port : cell < other.cell; - } -}; - struct ClockDomainKey { IdString clock; @@ -58,48 +38,7 @@ struct ClockDomainKey inline bool operator==(const ClockDomainKey &other) const { return (clock == other.clock) && (edge == other.edge); } }; -// TODO: perhaps move these elsewhere -struct FalsePath -{ -}; - -struct MinMaxDelay -{ - enum class Type - { - MAXDELAY, - MINDELAY - }; - - [[maybe_unused]] static const std::string type_to_str(Type typ) - { - switch (typ) { - case Type::MAXDELAY: - return "MAXDELAY"; - case Type::MINDELAY: - return "MINDELAY"; - default: - log_error("Impossible MinMaxDelay::Type"); - } - } - - Type type; - delay_t delay; - bool datapath_only; -}; - -struct MultiCycle -{ - size_t cycles; -}; - -struct TimingException -{ - std::variant type; - - pool startpoints; - pool endpoints; -}; +typedef int exception_id_t; typedef int domain_id_t; @@ -114,8 +53,6 @@ struct ClockDomainPairKey unsigned int hash() const { return mkhash(launch, capture); } }; -typedef int constraint_id_t; - struct TimingAnalyser { public: @@ -233,9 +170,15 @@ struct TimingAnalyser : type(type), other_port(other_port), value(value), edge(edge){}; }; - enum HasConstraint + // To track whether a path has a timing exception during a forwards/backwards pass. + // During the forward pass the startpoints propagate out FORWARDONLY. + // During the backwards pass all ports that contain a "FORWARDONLY" will + // move to "CONSTRAINED". Once the forward and backward passes have been + // done only the constraints on ports that are "CONSTRAINED" apply. + enum class HasPathException { FORWARDONLY, + BACKWARDONLY, CONSTRAINED }; @@ -258,7 +201,7 @@ struct TimingAnalyser worst_hold_slack = std::numeric_limits::max(); // Forall timing constraints the uint8_t indicates // - During forward walking - dict per_constraint; + dict per_timing_exception; }; struct PerDomain @@ -284,9 +227,7 @@ struct TimingAnalyser domain_id_t domain_id(const NetInfo *net, ClockEdge edge); domain_id_t domain_pair_id(domain_id_t launch, domain_id_t capture); - void copy_domains(const CellPortKey &from, const CellPortKey &to, bool backwards); - - void propagate_constraints(const CellPortKey &from, const CellPortKey &to, bool backwards); + void propagate_domains_and_constraints(const CellPortKey &from, const CellPortKey &to, bool backwards); [[maybe_unused]] static const std::string arcType_to_str(CellArc::ArcType typ); @@ -296,11 +237,12 @@ struct TimingAnalyser std::vector domains; std::vector domain_pairs; dict, delay_t> clock_delays; + // std::vector path_constraints; std::vector topological_order; domain_id_t async_clock_id; - constraint_id_t clock_constraint_id; + exception_id_t no_exception_id; Context *ctx;