Using hashlib in timing
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
ecc19c2c08
commit
b8a68f5f35
@ -23,7 +23,6 @@
|
|||||||
#include <boost/range/adaptor/reversed.hpp>
|
#include <boost/range/adaptor/reversed.hpp>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@ -272,7 +271,7 @@ void TimingAnalyser::setup_port_domains()
|
|||||||
void TimingAnalyser::reset_times()
|
void TimingAnalyser::reset_times()
|
||||||
{
|
{
|
||||||
for (auto &port : ports) {
|
for (auto &port : ports) {
|
||||||
auto do_reset = [&](std::unordered_map<domain_id_t, ArrivReqTime> ×) {
|
auto do_reset = [&](dict<domain_id_t, ArrivReqTime> ×) {
|
||||||
for (auto &t : times) {
|
for (auto &t : times) {
|
||||||
t.second.value = init_delay;
|
t.second.value = init_delay;
|
||||||
t.second.path_length = 0;
|
t.second.path_length = 0;
|
||||||
@ -426,7 +425,7 @@ void TimingAnalyser::walk_backward()
|
|||||||
void TimingAnalyser::print_fmax()
|
void TimingAnalyser::print_fmax()
|
||||||
{
|
{
|
||||||
// Temporary testing code for comparison only
|
// Temporary testing code for comparison only
|
||||||
std::unordered_map<int, double> domain_fmax;
|
dict<int, double> domain_fmax;
|
||||||
for (auto p : topological_order) {
|
for (auto p : topological_order) {
|
||||||
auto &pd = ports.at(p);
|
auto &pd = ports.at(p);
|
||||||
for (auto &req : pd.required) {
|
for (auto &req : pd.required) {
|
||||||
@ -591,6 +590,7 @@ struct ClockEvent
|
|||||||
ClockEdge edge;
|
ClockEdge edge;
|
||||||
|
|
||||||
bool operator==(const ClockEvent &other) const { return clock == other.clock && edge == other.edge; }
|
bool operator==(const ClockEvent &other) const { return clock == other.clock && edge == other.edge; }
|
||||||
|
unsigned int hash() const { return mkhash(clock.hash(), int(edge)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ClockPair
|
struct ClockPair
|
||||||
@ -598,37 +598,10 @@ struct ClockPair
|
|||||||
ClockEvent start, end;
|
ClockEvent start, end;
|
||||||
|
|
||||||
bool operator==(const ClockPair &other) const { return start == other.start && end == other.end; }
|
bool operator==(const ClockPair &other) const { return start == other.start && end == other.end; }
|
||||||
|
unsigned int hash() const { return mkhash(start.hash(), end.hash()); }
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
|
||||||
namespace std {
|
|
||||||
|
|
||||||
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX ClockEvent>
|
|
||||||
{
|
|
||||||
std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX ClockEvent &obj) const noexcept
|
|
||||||
{
|
|
||||||
std::size_t seed = 0;
|
|
||||||
boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(obj.clock));
|
|
||||||
boost::hash_combine(seed, hash<int>()(int(obj.edge)));
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX ClockPair>
|
|
||||||
{
|
|
||||||
std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX ClockPair &obj) const noexcept
|
|
||||||
{
|
|
||||||
std::size_t seed = 0;
|
|
||||||
boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX ClockEvent>()(obj.start));
|
|
||||||
boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX ClockEvent>()(obj.start));
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace std
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
typedef std::vector<const PortRef *> PortRefVector;
|
typedef std::vector<const PortRef *> PortRefVector;
|
||||||
typedef std::map<int, unsigned> DelayFrequency;
|
typedef std::map<int, unsigned> DelayFrequency;
|
||||||
|
|
||||||
@ -639,7 +612,7 @@ struct CriticalPath
|
|||||||
delay_t path_period;
|
delay_t path_period;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unordered_map<ClockPair, CriticalPath> CriticalPathMap;
|
typedef dict<ClockPair, CriticalPath> CriticalPathMap;
|
||||||
|
|
||||||
struct Timing
|
struct Timing
|
||||||
{
|
{
|
||||||
@ -660,7 +633,7 @@ struct Timing
|
|||||||
delay_t min_remaining_budget;
|
delay_t min_remaining_budget;
|
||||||
bool false_startpoint = false;
|
bool false_startpoint = false;
|
||||||
std::vector<delay_t> min_required;
|
std::vector<delay_t> min_required;
|
||||||
std::unordered_map<ClockEvent, delay_t> arrival_time;
|
dict<ClockEvent, delay_t> arrival_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
Timing(Context *ctx, bool net_delays, bool update, CriticalPathMap *crit_path = nullptr,
|
Timing(Context *ctx, bool net_delays, bool update, CriticalPathMap *crit_path = nullptr,
|
||||||
@ -677,14 +650,14 @@ struct Timing
|
|||||||
// First, compute the topological order of nets to walk through the circuit, assuming it is a _acyclic_ graph
|
// First, compute the topological order of nets to walk through the circuit, assuming it is a _acyclic_ graph
|
||||||
// TODO(eddieh): Handle the case where it is cyclic, e.g. combinatorial loops
|
// TODO(eddieh): Handle the case where it is cyclic, e.g. combinatorial loops
|
||||||
std::vector<NetInfo *> topological_order;
|
std::vector<NetInfo *> topological_order;
|
||||||
std::unordered_map<const NetInfo *, std::unordered_map<ClockEvent, TimingData>> net_data;
|
dict<const NetInfo *, dict<ClockEvent, TimingData>, hash_ptr_ops> net_data;
|
||||||
// In lieu of deleting edges from the graph, simply count the number of fanins to each output port
|
// In lieu of deleting edges from the graph, simply count the number of fanins to each output port
|
||||||
std::unordered_map<const PortInfo *, unsigned> port_fanin;
|
dict<const PortInfo *, unsigned, hash_ptr_ops> port_fanin;
|
||||||
|
|
||||||
std::vector<IdString> input_ports;
|
std::vector<IdString> input_ports;
|
||||||
std::vector<const PortInfo *> output_ports;
|
std::vector<const PortInfo *> output_ports;
|
||||||
|
|
||||||
std::unordered_set<IdString> ooc_port_nets;
|
pool<IdString> ooc_port_nets;
|
||||||
|
|
||||||
// In out-of-context mode, top-level inputs look floating but aren't
|
// In out-of-context mode, top-level inputs look floating but aren't
|
||||||
if (bool_or_default(ctx->settings, ctx->id("arch.ooc"))) {
|
if (bool_or_default(ctx->settings, ctx->id("arch.ooc"))) {
|
||||||
@ -880,7 +853,7 @@ struct Timing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<ClockPair, std::pair<delay_t, NetInfo *>> crit_nets;
|
dict<ClockPair, std::pair<delay_t, NetInfo *>> crit_nets;
|
||||||
|
|
||||||
// Now go backwards topologically to determine the minimum path slack, and to distribute all path slack evenly
|
// Now go backwards topologically to determine the minimum path slack, and to distribute all path slack evenly
|
||||||
// between all nets on the path
|
// between all nets on the path
|
||||||
|
@ -35,15 +35,7 @@ struct CellPortKey
|
|||||||
port = pr.port;
|
port = pr.port;
|
||||||
}
|
}
|
||||||
IdString cell, port;
|
IdString cell, port;
|
||||||
struct Hash
|
unsigned int hash() const { return mkhash(cell.hash(), port.hash()); }
|
||||||
{
|
|
||||||
inline std::size_t operator()(const CellPortKey &arg) const noexcept
|
|
||||||
{
|
|
||||||
std::size_t seed = std::hash<IdString>()(arg.cell);
|
|
||||||
seed ^= std::hash<IdString>()(arg.port) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
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); }
|
inline bool operator!=(const CellPortKey &other) const { return (cell != other.cell) || (port != other.port); }
|
||||||
inline bool operator<(const CellPortKey &other) const
|
inline bool operator<(const CellPortKey &other) const
|
||||||
@ -69,15 +61,8 @@ struct NetPortKey
|
|||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Hash
|
unsigned int hash() const { return mkhash(net.hash(), idx); }
|
||||||
{
|
|
||||||
std::size_t operator()(const NetPortKey &arg) const noexcept
|
|
||||||
{
|
|
||||||
std::size_t seed = std::hash<IdString>()(arg.net);
|
|
||||||
seed ^= std::hash<size_t>()(arg.idx) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
inline bool operator==(const NetPortKey &other) const { return (net == other.net) && (idx == other.idx); }
|
inline bool operator==(const NetPortKey &other) const { return (net == other.net) && (idx == other.idx); }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -89,15 +74,8 @@ struct ClockDomainKey
|
|||||||
// probably also need something here to deal with constraints
|
// probably also need something here to deal with constraints
|
||||||
inline bool is_async() const { return clock == IdString(); }
|
inline bool is_async() const { return clock == IdString(); }
|
||||||
|
|
||||||
struct Hash
|
unsigned int hash() const { return mkhash(clock.hash(), int(edge)); }
|
||||||
{
|
|
||||||
std::size_t operator()(const ClockDomainKey &arg) const noexcept
|
|
||||||
{
|
|
||||||
std::size_t seed = std::hash<IdString>()(arg.clock);
|
|
||||||
seed ^= std::hash<int>()(int(arg.edge)) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
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); }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -111,15 +89,7 @@ struct ClockDomainPairKey
|
|||||||
{
|
{
|
||||||
return (launch == other.launch) && (capture == other.capture);
|
return (launch == other.launch) && (capture == other.capture);
|
||||||
}
|
}
|
||||||
struct Hash
|
unsigned int hash() const { return mkhash(launch, capture); }
|
||||||
{
|
|
||||||
std::size_t operator()(const ClockDomainPairKey &arg) const noexcept
|
|
||||||
{
|
|
||||||
std::size_t seed = std::hash<domain_id_t>()(arg.launch);
|
|
||||||
seed ^= std::hash<domain_id_t>()(arg.capture) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TimingAnalyser
|
struct TimingAnalyser
|
||||||
@ -223,16 +193,17 @@ struct TimingAnalyser
|
|||||||
NetPortKey net_port;
|
NetPortKey net_port;
|
||||||
PortType type;
|
PortType type;
|
||||||
// per domain timings
|
// per domain timings
|
||||||
std::unordered_map<domain_id_t, ArrivReqTime> arrival;
|
dict<domain_id_t, ArrivReqTime> arrival;
|
||||||
std::unordered_map<domain_id_t, ArrivReqTime> required;
|
dict<domain_id_t, ArrivReqTime> required;
|
||||||
std::unordered_map<domain_id_t, PortDomainPairData> domain_pairs;
|
dict<domain_id_t, PortDomainPairData> domain_pairs;
|
||||||
// cell timing arcs to (outputs)/from (inputs) from this port
|
// cell timing arcs to (outputs)/from (inputs) from this port
|
||||||
std::vector<CellArc> cell_arcs;
|
std::vector<CellArc> cell_arcs;
|
||||||
// routing delay into this port (input ports only)
|
// routing delay into this port (input ports only)
|
||||||
DelayPair route_delay;
|
DelayPair route_delay{0};
|
||||||
// worst criticality and slack across domain pairs
|
// worst criticality and slack across domain pairs
|
||||||
float worst_crit;
|
float worst_crit = 0;
|
||||||
delay_t worst_setup_slack, worst_hold_slack;
|
delay_t worst_setup_slack = std::numeric_limits<delay_t>::max(),
|
||||||
|
worst_hold_slack = std::numeric_limits<delay_t>::max();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PerDomain
|
struct PerDomain
|
||||||
@ -260,9 +231,9 @@ struct TimingAnalyser
|
|||||||
|
|
||||||
void copy_domains(const CellPortKey &from, const CellPortKey &to, bool backwards);
|
void copy_domains(const CellPortKey &from, const CellPortKey &to, bool backwards);
|
||||||
|
|
||||||
std::unordered_map<CellPortKey, PerPort, CellPortKey::Hash> ports;
|
dict<CellPortKey, PerPort> ports;
|
||||||
std::unordered_map<ClockDomainKey, domain_id_t, ClockDomainKey::Hash> domain_to_id;
|
dict<ClockDomainKey, domain_id_t> domain_to_id;
|
||||||
std::unordered_map<ClockDomainPairKey, domain_id_t, ClockDomainPairKey::Hash> pair_to_id;
|
dict<ClockDomainPairKey, domain_id_t> pair_to_id;
|
||||||
std::vector<PerDomain> domains;
|
std::vector<PerDomain> domains;
|
||||||
std::vector<PerDomainPair> domain_pairs;
|
std::vector<PerDomainPair> domain_pairs;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user