diff options
-rw-r--r-- | common/placer1.cc | 148 | ||||
-rw-r--r-- | common/timing.cc | 21 |
2 files changed, 113 insertions, 56 deletions
diff --git a/common/placer1.cc b/common/placer1.cc index ee12f7f4..efa8a674 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -119,6 +119,12 @@ class SAPlacer region_bounds[r->name] = bb; } build_port_index(); + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); + if (ci->cluster == ClusterId()) + continue; + cluster2cell[ci->cluster].push_back(ci); + } } ~SAPlacer() @@ -616,56 +622,95 @@ class SAPlacer bool try_swap_chain(CellInfo *cell, BelId newBase) { std::vector<std::pair<CellInfo *, Loc>> cell_rel; - pool<IdString> cells; - std::vector<std::pair<CellInfo *, BelId>> moves_made; + dict<IdString, BelId> moved_cells; std::vector<std::pair<CellInfo *, BelId>> dest_bels; double delta = 0; int orig_share_cost = total_net_share; moveChange.reset(this); -#if 0 - if (ctx->debug) - log_info("finding cells for chain swap %s\n", cell->name.c_str(ctx)); +#if CHAIN_DEBUG + log_info("finding cells for chain swap %s\n", cell->name.c_str(ctx)); #endif - if (!ctx->getClusterPlacement(cell->cluster, newBase, dest_bels)) - return false; - - for (const auto &db : dest_bels) - cells.insert(db.first->name); - - for (const auto &db : dest_bels) { - CellInfo *bound = ctx->getBoundBelCell(db.second); - // We don't consider swapping chains with other chains, at least for the time being - unless it is - // part of this chain - if (bound != nullptr && !cells.count(bound->name) && - (bound->belStrength >= STRENGTH_STRONG || bound->cluster != ClusterId())) - return false; - - if (bound != nullptr) - if (!ctx->isValidBelForCellType(bound->type, db.first->bel)) - return false; - } -#if 0 - if (ctx->debug) - log_info("trying chain swap %s\n", cell->name.c_str(ctx)); + std::queue<std::pair<ClusterId, BelId>> displaced_clusters; + displaced_clusters.emplace(cell->cluster, newBase); + while (!displaced_clusters.empty()) { + auto cursor = displaced_clusters.front(); + displaced_clusters.pop(); + if (!ctx->getClusterPlacement(cursor.first, cursor.second, dest_bels)) + goto swap_fail; + for (const auto &db : dest_bels) { + // Ensure the cluster is ripped up + if (db.first->bel != BelId()) { + moved_cells[db.first->name] = db.first->bel; +#if CHAIN_DEBUG + log_info("%d unbind %s\n", __LINE__, ctx->nameOfBel(db.first->bel)); +#endif + ctx->unbindBel(db.first->bel); + } + } + for (const auto &db : dest_bels) { + CellInfo *bound = ctx->getBoundBelCell(db.second); + BelId old_bel = moved_cells.at(db.first->name); + if (!ctx->checkBelAvail(old_bel) && bound != nullptr) { + // Simple swap no longer possible + goto swap_fail; + } + if (bound != nullptr) { + if (moved_cells.count(bound->name)) { + // Don't move a cell multiple times in the same go + goto swap_fail; + } else if (bound->belStrength > STRENGTH_STRONG) { + goto swap_fail; + } else if (bound->cluster != ClusterId()) { + // Displace the entire cluster + Loc old_loc = ctx->getBelLocation(old_bel); + Loc bound_loc = ctx->getBelLocation(bound->bel); + Loc root_loc = ctx->getBelLocation(ctx->getClusterRootCell(bound->cluster)->bel); + BelId new_root = ctx->getBelByLocation(Loc(old_loc.x + (root_loc.x - bound_loc.x), + old_loc.y + (root_loc.y - bound_loc.y), + old_loc.z + (root_loc.z - bound_loc.z))); + if (new_root == BelId()) + goto swap_fail; + for (auto cluster_cell : cluster2cell.at(bound->cluster)) { + moved_cells[cluster_cell->name] = cluster_cell->bel; +#if CHAIN_DEBUG + log_info("%d unbind %s\n", __LINE__, ctx->nameOfBel(cluster_cell->bel)); +#endif + ctx->unbindBel(cluster_cell->bel); + } + displaced_clusters.emplace(bound->cluster, new_root); + } else { + // Just a single cell to move + moved_cells[bound->name] = bound->bel; +#if CHAIN_DEBUG + log_info("%d unbind %s\n", __LINE__, ctx->nameOfBel(bound->bel)); + log_info("%d bind %s %s\n", __LINE__, ctx->nameOfBel(old_bel), ctx->nameOf(bound)); +#endif + ctx->unbindBel(bound->bel); + ctx->bindBel(old_bel, bound, STRENGTH_WEAK); + } + } else if (!ctx->checkBelAvail(db.second)) { + goto swap_fail; + } + // All those shenanigans should now mean the target bel is free to use +#if CHAIN_DEBUG + log_info("%d bind %s %s\n", __LINE__, ctx->nameOfBel(db.second), ctx->nameOf(db.first)); #endif - // <cell, oldBel> - for (const auto &db : dest_bels) { - BelId oldBel = swap_cell_bels(db.first, db.second); - moves_made.emplace_back(std::make_pair(db.first, oldBel)); - CellInfo *bound = ctx->getBoundBelCell(oldBel); - add_move_cell(moveChange, db.first, oldBel); - if (bound != nullptr) - add_move_cell(moveChange, bound, db.second); + ctx->bindBel(db.second, db.first, STRENGTH_WEAK); + } } - for (const auto &mm : moves_made) { - if (!ctx->isBelLocationValid(mm.first->bel) || !mm.first->testRegion(mm.first->bel)) - goto swap_fail; - if (!ctx->isBelLocationValid(mm.second)) - goto swap_fail; - CellInfo *bound = ctx->getBoundBelCell(mm.second); - if (bound && !bound->testRegion(bound->bel)) + + for (const auto &mm : moved_cells) { + CellInfo *cell = ctx->cells.at(mm.first).get(); + add_move_cell(moveChange, cell, moved_cells.at(cell->name)); + if (cfg.netShareWeight > 0) + update_nets_by_tile(cell, ctx->getBelLocation(moved_cells.at(cell->name)), + ctx->getBelLocation(cell->bel)); + if (!ctx->isBelLocationValid(cell->bel) || !cell->testRegion(cell->bel)) goto swap_fail; } +#if CHAIN_DEBUG + log_info("legal chain swap %s\n", cell->name.c_str(ctx)); +#endif compute_cost_changes(moveChange); delta = lambda * (moveChange.timing_delta / last_timing_cost) + (1 - lambda) * (double(moveChange.wirelen_delta) / last_wirelen_cost); @@ -675,11 +720,10 @@ class SAPlacer } n_move++; // SA acceptance criteria - if (delta < 0 || (temp > 1e-9 && (ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) { + if (delta < 0 || (temp > 1e-8 && (ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) { n_accept++; -#if 0 - if (ctx->debug) - log_info("accepted chain swap %s\n", cell->name.c_str(ctx)); +#if CHAIN_DEBUG + log_info("accepted chain swap %s\n", cell->name.c_str(ctx)); #endif } else { goto swap_fail; @@ -687,8 +731,15 @@ class SAPlacer commit_cost_changes(moveChange); return true; swap_fail: - for (const auto &entry : boost::adaptors::reverse(moves_made)) - swap_cell_bels(entry.first, entry.second); + for (auto cell_pair : moved_cells) { + CellInfo *cell = ctx->cells.at(cell_pair.first).get(); + if (cell->bel != BelId()) + ctx->unbindBel(cell->bel); + } + for (auto cell_pair : moved_cells) { + CellInfo *cell = ctx->cells.at(cell_pair.first).get(); + ctx->bindBel(cell_pair.second, cell, STRENGTH_WEAK); + } return false; } @@ -1183,6 +1234,9 @@ class SAPlacer // Fast lookup for cell port to net user index dict<std::pair<IdString, IdString>, size_t> fast_port_to_user; + // Fast lookup for cell to clusters + dict<ClusterId, std::vector<CellInfo *>> cluster2cell; + // Wirelength and timing cost at last and current iteration wirelen_t last_wirelen_cost, curr_wirelen_cost; double last_timing_cost, curr_timing_cost; diff --git a/common/timing.cc b/common/timing.cc index 161769dc..ce293f34 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -275,12 +275,13 @@ void TimingAnalyser::setup_port_domains() if (launch_data.key.clock != capture_data.key.clock) continue; IdString clk = launch_data.key.clock; - if (!ctx->nets.count(clk)) - continue; - NetInfo *clk_net = ctx->nets.at(clk).get(); - if (!clk_net->clkconstr) - continue; - delay_t period = clk_net->clkconstr->period.minDelay(); + delay_t period = ctx->getDelayFromNS(1.0e9 / ctx->setting<float>("target_freq")); + if (ctx->nets.count(clk)) { + NetInfo *clk_net = ctx->nets.at(clk).get(); + if (clk_net->clkconstr) { + period = clk_net->clkconstr->period.minDelay(); + } + } if (launch_data.key.edge != capture_data.key.edge) period /= 2; dp.period = DelayPair(period); @@ -426,15 +427,17 @@ void TimingAnalyser::walk_backward() // Input port: propagate delay back through net, subtracting route delay NetInfo *net = port_info(p).net; if (net != nullptr && net->driver.cell != nullptr) - set_required_time(CellPortKey(net->driver), req.first, req.second.value - pd.route_delay, - req.second.path_length, p); + set_required_time(CellPortKey(net->driver), req.first, + req.second.value - DelayPair(pd.route_delay.maxDelay()), req.second.path_length, + p); } else if (pd.type == PORT_OUT) { // Output port : propagate delay back through cell, subtracting combinational delay for (auto &fanin : pd.cell_arcs) { if (fanin.type != CellArc::COMBINATIONAL) continue; set_required_time(CellPortKey(p.cell, fanin.other_port), req.first, - req.second.value - fanin.value.delayPair(), req.second.path_length + 1, p); + req.second.value - DelayPair(fanin.value.maxDelay()), req.second.path_length + 1, + p); } } } |