diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/timing.cc | 2 | ||||
-rw-r--r-- | common/timing_opt.cc | 77 | ||||
-rw-r--r-- | common/timing_opt.h | 4 |
3 files changed, 83 insertions, 0 deletions
diff --git a/common/timing.cc b/common/timing.cc index 55d3a46f..ebe3a177 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -91,6 +91,7 @@ struct NetCriticalityInfo // One each per user std::vector<delay_t> slack; std::vector<float> criticality; + unsigned max_path_length = 0; }; typedef std::unordered_map<ClockPair, CriticalPath> CriticalPathMap; @@ -597,6 +598,7 @@ struct Timing float criticality = 1.0 - ((nc.slack.at(i) - worst_slack.at(startdomain.first)) / dmax); nc.criticality.at(i) = std::max(nc.criticality.at(i), criticality); } + nc.max_path_length = std::max(nc.max_path_length, nd.max_path_length); } } } diff --git a/common/timing_opt.cc b/common/timing_opt.cc index b33c2db0..de8e00a5 100644 --- a/common/timing_opt.cc +++ b/common/timing_opt.cc @@ -34,6 +34,83 @@ class TimingOptimiser bool optimise() {} private: + // Ratio of available to already-candidates to begin borrowing + const float borrow_thresh = 0.2; + + bool check_cell_delay_limits(CellInfo *cell) { + + } + + bool acceptable_bel_candidate(CellInfo *cell, BelId newBel) { + bool result = true; + // At the moment we have to actually do the swap to get an accurate legality result + // Switching to macro swaps might help with this + BelId oldBel = cell->bel; + CellInfo *other_cell = ctx->getBoundBelCell(newBel); + if (other_cell != nullptr && other_cell->belStrength > STRENGTH_WEAK) { + return false; + } + + ctx->bindBel(newBel, cell, STRENGTH_WEAK); + if (other_cell != nullptr) { + ctx->bindBel(oldBel, other_cell, STRENGTH_WEAK); + } + if (!ctx->isBelLocationValid(newBel) || ((other_cell != nullptr && !ctx->isBelLocationValid(oldBel)))) { + result = false; + goto unbind; + } + + + +unbind: + ctx->unbindBel(newBel); + if (other_cell != nullptr) + ctx->unbindBel(oldBel); + // Undo the swap + ctx->bindBel(oldBel, cell, STRENGTH_WEAK); + if (other_cell != nullptr) { + ctx->bindBel(newBel, other_cell, STRENGTH_WEAK); + } + return result; + } + + void find_neighbours(CellInfo *cell, int d) { + BelId curr = cell->bel; + Loc curr_loc = ctx->getBelLocation(curr); + for (int dy = -d; dy <= d; dy++) { + for (int dx = -d; dx <= d; dx++) { + if (dx == 0 && dy == 0) + continue; + // Go through all the Bels at this location + // First, find all bels of the correct type that are either unbound or bound normally + // Strongly bound bels are ignored + // FIXME: This means that we cannot touch carry chains or similar relatively constrained macros + std::vector<BelId> free_bels_at_loc; + std::vector<BelId> bound_bels_at_loc; + for (auto bel : ctx->getBelsByTile(curr_loc.x + dx, curr_loc.y + dy)) { + if (ctx->getBelType(bel) != cell->type) + continue; + CellInfo *bound = ctx->getBoundBelCell(bel); + if (bound == nullptr) { + free_bels_at_loc.push_back(bel); + } else if (bound->belStrength <= STRENGTH_WEAK) { + bound_bels_at_loc.push_back(bel); + } + } + bool found = false; + + if (found) + continue; + } + } + } + + // Current candidate Bels for cells (linked in both direction> + std::vector<IdString> path_cells; + std::unordered_map<IdString, std::unordered_set<BelId>> cell_neighbour_bels; + std::unordered_map<BelId, std::unordered_set<IdString>> bel_candidate_cells; + // Map net users to net delay limit + std::unordered_map<IdString, std::vector<delay_t>> max_net_delay; Context *ctx; }; diff --git a/common/timing_opt.h b/common/timing_opt.h index 60df7df9..746294bb 100644 --- a/common/timing_opt.h +++ b/common/timing_opt.h @@ -23,6 +23,10 @@ NEXTPNR_NAMESPACE_BEGIN struct TimingOptCfg : public Settings { + // The timing optimiser will *only* optimise cells of these types + // Normally these would only be logic cells (or tiles if applicable), the algorithm makes little sense + // for other cell types + std::unordered_set<IdString> cellTypes; }; extern bool timing_opt(Context *ctx, TimingOptCfg cfg); |