timing: Start TimingException implementation
This commit is contained in:
parent
437fb70ed3
commit
334ac9d13a
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user