timing: Start TimingException implementation

This commit is contained in:
Rowan Goemans 2024-09-23 12:22:57 +02:00
parent 437fb70ed3
commit 334ac9d13a
2 changed files with 83 additions and 7 deletions

View File

@ -42,7 +42,7 @@ void TimingAnalyser::setup(bool update_net_timings, bool update_histogram, bool
init_ports(); init_ports();
get_cell_delays(); get_cell_delays();
topo_sort(); topo_sort();
setup_port_domains(); setup_port_domains_and_constraints();
identify_related_domains(); identify_related_domains();
run(true, update_net_timings, update_histogram, update_crit_paths); run(true, update_net_timings, update_histogram, update_crit_paths);
} }
@ -229,7 +229,7 @@ void TimingAnalyser::topo_sort()
std::swap(topological_order, topo.sorted); std::swap(topological_order, topo.sorted);
} }
void TimingAnalyser::setup_port_domains() void TimingAnalyser::setup_port_domains_and_constraints()
{ {
for (auto &d : domains) { for (auto &d : domains) {
d.startpoints.clear(); d.startpoints.clear();
@ -238,7 +238,7 @@ void TimingAnalyser::setup_port_domains()
bool first_iter = true; bool first_iter = true;
do { do {
// Go forward through the topological order (domains from the PoV of arrival time) // 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) { for (auto port : topological_order) {
auto &pd = ports.at(port); auto &pd = ports.at(port);
auto &pi = port_info(port); auto &pi = port_info(port);
@ -256,6 +256,7 @@ void TimingAnalyser::setup_port_domains()
// create per-domain data // create per-domain data
pd.arrival[dom]; pd.arrival[dom];
domains.at(dom).startpoints.emplace_back(port, fanin.other_port); domains.at(dom).startpoints.emplace_back(port, fanin.other_port);
// TODO: add all constraints on this startpoint
} }
} }
// copy domains across routing // copy domains across routing
@ -296,6 +297,7 @@ void TimingAnalyser::setup_port_domains()
// create per-domain data // create per-domain data
pd.required[dom]; pd.required[dom];
domains.at(dom).endpoints.emplace_back(port, fanout.other_port); domains.at(dom).endpoints.emplace_back(port, fanout.other_port);
// TODO: add all constraints on this endpoint
} }
} }
// copy port to driver // copy port to driver
@ -314,7 +316,7 @@ void TimingAnalyser::setup_port_domains()
first_iter = false; first_iter = false;
// If there are loops, repeat the process until a fixed point is reached, as there might be unusual ways to // 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 // 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) { for (auto &dp : domain_pairs) {
auto &launch_data = domains.at(dp.key.launch); auto &launch_data = domains.at(dp.key.launch);
auto &capture_data = domains.at(dp.key.capture); 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); auto &f = ports.at(from), &t = ports.at(to);
for (auto &dom : (backward ? f.required : f.arrival)) { 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;
}
} }
} }

View File

@ -58,6 +58,49 @@ struct ClockDomainKey
inline bool operator==(const ClockDomainKey &other) const { return (clock == other.clock) && (edge == other.edge); } 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<FalsePath, MinMaxDelay, MultiCycle> type;
pool<CellPortKey> startpoints;
pool<CellPortKey> endpoints;
};
typedef int domain_id_t; typedef int domain_id_t;
struct ClockDomainPairKey struct ClockDomainPairKey
@ -71,6 +114,8 @@ struct ClockDomainPairKey
unsigned int hash() const { return mkhash(launch, capture); } unsigned int hash() const { return mkhash(launch, capture); }
}; };
typedef int constraint_id_t;
struct TimingAnalyser struct TimingAnalyser
{ {
public: public:
@ -103,14 +148,14 @@ struct TimingAnalyser
bool setup_only = false; bool setup_only = false;
bool have_loops = false; bool have_loops = false;
bool updated_domains = false; bool updated_domains_constraints = false;
private: private:
void init_ports(); void init_ports();
void get_cell_delays(); void get_cell_delays();
void get_route_delays(); void get_route_delays();
void topo_sort(); void topo_sort();
void setup_port_domains(); void setup_port_domains_and_constraints();
void identify_related_domains(); void identify_related_domains();
void reset_times(); void reset_times();
@ -188,6 +233,12 @@ struct TimingAnalyser
: type(type), other_port(other_port), value(value), edge(edge){}; : type(type), other_port(other_port), value(value), edge(edge){};
}; };
enum HasConstraint
{
FORWARDONLY,
CONSTRAINED
};
// Timing data for every cell port // Timing data for every cell port
struct PerPort struct PerPort
{ {
@ -205,6 +256,9 @@ struct TimingAnalyser
float worst_crit = 0; float worst_crit = 0;
delay_t worst_setup_slack = std::numeric_limits<delay_t>::max(), delay_t worst_setup_slack = std::numeric_limits<delay_t>::max(),
worst_hold_slack = std::numeric_limits<delay_t>::max(); worst_hold_slack = std::numeric_limits<delay_t>::max();
// Forall timing constraints the uint8_t indicates
// - During forward walking
dict<constraint_id_t, uint8_t> per_constraint;
}; };
struct PerDomain struct PerDomain
@ -232,6 +286,8 @@ struct TimingAnalyser
void copy_domains(const CellPortKey &from, const CellPortKey &to, bool backwards); 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); [[maybe_unused]] static const std::string arcType_to_str(CellArc::ArcType typ);
dict<CellPortKey, PerPort> ports; dict<CellPortKey, PerPort> ports;
@ -244,6 +300,7 @@ struct TimingAnalyser
std::vector<CellPortKey> topological_order; std::vector<CellPortKey> topological_order;
domain_id_t async_clock_id; domain_id_t async_clock_id;
constraint_id_t clock_constraint_id;
Context *ctx; Context *ctx;