common: Move CellPortKey to nextpnr_types.h
This commit is contained in:
parent
334ac9d13a
commit
92a92abd56
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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<FalsePath, MinMaxDelay, MultiCycle> type;
|
||||
|
||||
pool<CellPortKey> startpoints;
|
||||
pool<CellPortKey> 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<delay_t>::max();
|
||||
// Forall timing constraints the uint8_t indicates
|
||||
// - During forward walking
|
||||
dict<constraint_id_t, uint8_t> per_constraint;
|
||||
dict<exception_id_t, uint8_t> 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<PerDomain> domains;
|
||||
std::vector<PerDomainPair> domain_pairs;
|
||||
dict<std::pair<IdString, IdString>, delay_t> clock_delays;
|
||||
// std::vector<PathConstraint> path_constraints;
|
||||
|
||||
std::vector<CellPortKey> topological_order;
|
||||
|
||||
domain_id_t async_clock_id;
|
||||
constraint_id_t clock_constraint_id;
|
||||
exception_id_t no_exception_id;
|
||||
|
||||
Context *ctx;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user