timing_opt: Implement neighbour Bel finder

Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
David Shah 2018-12-01 13:22:57 +00:00
parent 9a42b64a68
commit 83e3277577
3 changed files with 83 additions and 0 deletions

View File

@ -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);
}
}
}

View File

@ -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;
};

View File

@ -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);