From 5a5a282b26c6fc602a40b9de77aaac6082800fd4 Mon Sep 17 00:00:00 2001 From: Rowan Goemans Date: Mon, 23 Sep 2024 12:22:57 +0200 Subject: [PATCH] timing: Start TimingException implementation --- common/kernel/timing.cc | 29 ++++++++++++++++---- common/kernel/timing.h | 61 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 7 deletions(-) diff --git a/common/kernel/timing.cc b/common/kernel/timing.cc index 880cc50691..2cc7cd63ac 100644 --- a/common/kernel/timing.cc +++ b/common/kernel/timing.cc @@ -42,7 +42,7 @@ void TimingAnalyser::setup(bool update_net_timings, bool update_histogram, bool init_ports(); get_cell_delays(); topo_sort(); - setup_port_domains(); + setup_port_domains_and_constraints(); identify_related_domains(); run(true, update_net_timings, update_histogram, update_crit_paths); } @@ -229,7 +229,7 @@ void TimingAnalyser::topo_sort() std::swap(topological_order, topo.sorted); } -void TimingAnalyser::setup_port_domains() +void TimingAnalyser::setup_port_domains_and_constraints() { for (auto &d : domains) { d.startpoints.clear(); @@ -238,7 +238,7 @@ void TimingAnalyser::setup_port_domains() bool first_iter = true; do { // Go forward through the topological order (domains from the PoV of arrival time) - updated_domains = false; + updated_domains_constraints = false; for (auto port : topological_order) { auto &pd = ports.at(port); auto &pi = port_info(port); @@ -256,6 +256,7 @@ void TimingAnalyser::setup_port_domains() // create per-domain data pd.arrival[dom]; domains.at(dom).startpoints.emplace_back(port, fanin.other_port); + // TODO: add all constraints on this startpoint } } // copy domains across routing @@ -296,6 +297,7 @@ void TimingAnalyser::setup_port_domains() // create per-domain data pd.required[dom]; domains.at(dom).endpoints.emplace_back(port, fanout.other_port); + // TODO: add all constraints on this endpoint } } // copy port to driver @@ -314,7 +316,7 @@ void TimingAnalyser::setup_port_domains() first_iter = false; // If there are loops, repeat the process until a fixed point is reached, as there might be unusual ways to // visit points, which would result in a missing domain key and therefore crash later on - } while (have_loops && updated_domains); + } while (have_loops && updated_domains_constraints); for (auto &dp : domain_pairs) { auto &launch_data = domains.at(dp.key.launch); auto &capture_data = domains.at(dp.key.capture); @@ -1298,7 +1300,24 @@ void TimingAnalyser::copy_domains(const CellPortKey &from, const CellPortKey &to { auto &f = ports.at(from), &t = ports.at(to); for (auto &dom : (backward ? f.required : f.arrival)) { - updated_domains |= (backward ? t.required : t.arrival).emplace(dom.first, ArrivReqTime{}).second; + 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; + + 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; + } } } diff --git a/common/kernel/timing.h b/common/kernel/timing.h index f82a1b6da6..1915f9ec23 100644 --- a/common/kernel/timing.h +++ b/common/kernel/timing.h @@ -58,6 +58,49 @@ 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 domain_id_t; struct ClockDomainPairKey @@ -71,6 +114,8 @@ struct ClockDomainPairKey unsigned int hash() const { return mkhash(launch, capture); } }; +typedef int constraint_id_t; + struct TimingAnalyser { public: @@ -103,14 +148,14 @@ struct TimingAnalyser bool setup_only = false; bool have_loops = false; - bool updated_domains = false; + bool updated_domains_constraints = false; private: void init_ports(); void get_cell_delays(); void get_route_delays(); void topo_sort(); - void setup_port_domains(); + void setup_port_domains_and_constraints(); void identify_related_domains(); void reset_times(); @@ -188,6 +233,12 @@ struct TimingAnalyser : type(type), other_port(other_port), value(value), edge(edge){}; }; + enum HasConstraint + { + FORWARDONLY, + CONSTRAINED + }; + // Timing data for every cell port struct PerPort { @@ -205,6 +256,9 @@ struct TimingAnalyser float worst_crit = 0; delay_t worst_setup_slack = std::numeric_limits::max(), worst_hold_slack = std::numeric_limits::max(); + // Forall timing constraints the uint8_t indicates + // - During forward walking + dict per_constraint; }; struct PerDomain @@ -232,6 +286,8 @@ struct TimingAnalyser void copy_domains(const CellPortKey &from, const CellPortKey &to, bool backwards); + void propagate_constraints(const CellPortKey &from, const CellPortKey &to, bool backwards); + [[maybe_unused]] static const std::string arcType_to_str(CellArc::ArcType typ); dict ports; @@ -244,6 +300,7 @@ struct TimingAnalyser std::vector topological_order; domain_id_t async_clock_id; + constraint_id_t clock_constraint_id; Context *ctx;