mirror of https://github.com/YosysHQ/nextpnr.git
Compare commits
2 Commits
6ad7c06795
...
d5c37d6354
| Author | SHA1 | Date |
|---|---|---|
|
|
d5c37d6354 | |
|
|
45d4a323a9 |
|
|
@ -788,6 +788,88 @@ void TimingAnalyser::compute_criticality()
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<ClockSkewPaths> TimingAnalyser::get_clock_skew_paths()
|
||||
{
|
||||
// The idea of this algorithm is to assign a unique ID to each clocked startpoint
|
||||
// per domain. We propagate the id through the topologically sorted netlist
|
||||
// if we notice a port allready has an id we unify that id with the incoming
|
||||
// id. Once we finish this propogation we now have a data structure
|
||||
// where startpoints and endpoints whose timing influences eachother through
|
||||
// clock skew have the same ID.
|
||||
std::deque<uint64_t> supply;
|
||||
uint64_t current = 0;
|
||||
|
||||
auto mk_new = [&]() {
|
||||
supply.emplace_back(current);
|
||||
current += 1;
|
||||
return &supply.back();
|
||||
};
|
||||
|
||||
auto unify = [&](uint64_t *lhs, uint64_t *rhs) { *lhs = *rhs; };
|
||||
|
||||
dict<CellPortKey, dict<domain_id_t, uint64_t *>> reachability;
|
||||
|
||||
for (domain_id_t dom_id = 0; dom_id < domain_id_t(domains.size()); ++dom_id) {
|
||||
auto &dom = domains.at(dom_id);
|
||||
for (auto &sp : dom.startpoints) {
|
||||
auto &pd = ports.at(sp.first);
|
||||
if (sp.second == IdString()) {
|
||||
continue;
|
||||
}
|
||||
for (auto &fanin : pd.cell_arcs) {
|
||||
if (fanin.type == CellArc::CLK_TO_Q && fanin.other_port == sp.second) {
|
||||
CellPortKey clock_key = CellPortKey(sp.first.cell, sp.second);
|
||||
auto clk_delay = ports.at(CellPortKey(sp.first.cell, fanin.other_port)).route_delay;
|
||||
reachability[sp.first][dom_id] = mk_new();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Walk forward in topological order propagate reachability
|
||||
for (auto p : topological_order) {
|
||||
auto &pd = ports.at(p);
|
||||
if (pd.type == PORT_OUT) {
|
||||
// Output port: propagate reachability through net
|
||||
NetInfo *net = port_info(p).net;
|
||||
if (net == nullptr) {
|
||||
continue;
|
||||
}
|
||||
auto &merge_driver = reachability[p];
|
||||
for (auto &usr : net->users) {
|
||||
CellPortKey usr_key(usr);
|
||||
auto &merge_sink = reachability[usr_key];
|
||||
for (auto &driver : merge_driver) {
|
||||
unify(driver.second, merge_sink[driver.first]);
|
||||
}
|
||||
}
|
||||
} else if (pd.type == PORT_IN) {
|
||||
// Input port; propagate reachability through cell
|
||||
auto &merge_driver = reachability[p];
|
||||
|
||||
for (auto &fanout : pd.cell_arcs) {
|
||||
if (fanout.type != CellArc::COMBINATIONAL)
|
||||
continue;
|
||||
|
||||
CellPortKey other_key(p.cell, fanout.other_port);
|
||||
auto &merge_sink = reachability[other_key];
|
||||
for (auto &driver : merge_driver) {
|
||||
unify(driver.second, merge_sink[driver.first]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Now we need to go throuch all start and endpoints grouping
|
||||
// them by the reachability identifier, querying the clock delays and
|
||||
// storing it in the result.
|
||||
|
||||
std::vector<ClockSkewPaths> result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void TimingAnalyser::build_detailed_net_timing_report()
|
||||
{
|
||||
auto &net_timings = result.detailed_net_timings;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,16 @@ struct CellPortKey
|
|||
}
|
||||
};
|
||||
|
||||
struct ClockSkewPaths
|
||||
{
|
||||
// Which clock this set is for.
|
||||
IdString clk;
|
||||
|
||||
// Startpoints and endpoints, the pair contains the clock port and the clock delay
|
||||
std::vector<std::pair<CellPortKey, delay_t>> startpoint_clk_ports;
|
||||
std::vector<std::pair<CellPortKey, delay_t>> endpoint_clk_ports;
|
||||
};
|
||||
|
||||
struct ClockDomainKey
|
||||
{
|
||||
IdString clock;
|
||||
|
|
@ -94,6 +104,12 @@ struct TimingAnalyser
|
|||
return slack;
|
||||
}
|
||||
|
||||
// Gives a list a set of startpoints and endpoints that have a timing dependency
|
||||
// via the clock path. Concretely that means that changing the clock delay to
|
||||
// a start- or endpoint willl impact the skew of all the clocks in the other
|
||||
// start- and endpoints.
|
||||
std::vector<ClockSkewPaths> get_clock_skew_paths();
|
||||
|
||||
dict<std::pair<IdString, IdString>, delay_t> get_clock_delays() const { return clock_delays; }
|
||||
|
||||
TimingResult &get_timing_result() { return result; }
|
||||
|
|
|
|||
Loading…
Reference in New Issue