diff options
author | gatecat <gatecat@ds0.me> | 2022-06-23 18:48:31 +0100 |
---|---|---|
committer | gatecat <gatecat@ds0.me> | 2022-07-08 14:30:57 +0200 |
commit | 09e388f453d9cf998391495349c88e5478b62e34 (patch) | |
tree | 004f2b14ed5a3b0584c4998d9f0a5598cc52ab28 /common/place | |
parent | 86396c41d64d2583ec1dffca4298e83d927f0762 (diff) | |
download | nextpnr-09e388f453d9cf998391495349c88e5478b62e34.tar.gz nextpnr-09e388f453d9cf998391495349c88e5478b62e34.tar.bz2 nextpnr-09e388f453d9cf998391495349c88e5478b62e34.zip |
netlist: Add PseudoCell API
When implementing concepts such as partition pins or deliberately split
nets, there's a need for something that looks like a cell (starts/ends
routing with pins on nets, has timing data) but isn't mapped to a fixed
bel in the architecture, but instead can have pin mappings defined at
runtime.
The PseudoCell allows this by providing an alternate, virtual-function
based API for such cells. When a cell has `pseudo_cell` used, instead of
calling functions such as getBelPinWire, getBelLocation or getCellDelay
in the Arch API; such data is provided by the cell itself, fully
flexible at runtime regardless of arch, via methods on the PseudoCell
implementation.
Diffstat (limited to 'common/place')
-rw-r--r-- | common/place/detail_place_core.cc | 12 | ||||
-rw-r--r-- | common/place/parallel_refine.cc | 2 | ||||
-rw-r--r-- | common/place/place_common.cc | 6 | ||||
-rw-r--r-- | common/place/placer1.cc | 20 | ||||
-rw-r--r-- | common/place/placer_heap.cc | 24 |
5 files changed, 50 insertions, 14 deletions
diff --git a/common/place/detail_place_core.cc b/common/place/detail_place_core.cc index 7e629f24..18118fc8 100644 --- a/common/place/detail_place_core.cc +++ b/common/place/detail_place_core.cc @@ -37,6 +37,8 @@ PlacePartition::PlacePartition(Context *ctx) x1 = 0; y1 = 0; for (auto &cell : ctx->cells) { + if (cell.second->isPseudo()) + continue; Loc l = ctx->getBelLocation(cell.second->bel); x0 = std::min(x0, l.x); x1 = std::max(x1, l.x); @@ -110,6 +112,8 @@ NetBB NetBB::compute(const Context *ctx, const NetInfo *net, const dict<IdString if (!net->driver.cell) return result; auto bel_loc = [&](const CellInfo *cell) { + if (cell->isPseudo()) + return cell->getLocation(); BelId bel = cell2bel ? cell2bel->at(cell->name) : cell->bel; return ctx->getBelLocation(bel); }; @@ -176,10 +180,12 @@ void DetailPlacerThreadState::set_partition(const PlacePartition &part) // Set up the original cell-bel map for all nets inside the thread local_cell2bel.clear(); for (NetInfo *net : thread_nets) { - if (net->driver.cell) + if (net->driver.cell && !net->driver.cell->isPseudo()) local_cell2bel[net->driver.cell->name] = net->driver.cell->bel; - for (auto &usr : net->users) - local_cell2bel[usr.cell->name] = usr.cell->bel; + for (auto &usr : net->users) { + if (!usr.cell->isPseudo()) + local_cell2bel[usr.cell->name] = usr.cell->bel; + } } } diff --git a/common/place/parallel_refine.cc b/common/place/parallel_refine.cc index de71b8e0..0fb99be5 100644 --- a/common/place/parallel_refine.cc +++ b/common/place/parallel_refine.cc @@ -390,6 +390,8 @@ struct ParallelRefine // Setup fast bels map pool<IdString> cell_types_in_use; for (auto &cell : ctx->cells) { + if (cell.second->isPseudo()) + continue; IdString cell_type = cell.second->type; cell_types_in_use.insert(cell_type); if (cell.second->cluster != ClusterId()) diff --git a/common/place/place_common.cc b/common/place/place_common.cc index e03fca55..c2fc3b7d 100644 --- a/common/place/place_common.cc +++ b/common/place/place_common.cc @@ -293,6 +293,8 @@ class ConstraintLegaliseWorker { if (cell->cluster != ClusterId() && ctx->getClusterRootCell(cell->cluster) != cell) return true; // Only process chain roots + if (cell->isPseudo()) + return true; if (constraints_satisfied(cell)) { if (cell->cluster != ClusterId()) lockdown_chain(cell); @@ -415,7 +417,7 @@ class ConstraintLegaliseWorker { log_info("Legalising relative constraints...\n"); for (auto &cell : ctx->cells) { - oldLocations[cell.first] = ctx->getBelLocation(cell.second->bel); + oldLocations[cell.first] = cell.second->getLocation(); } for (auto &cell : ctx->cells) { bool res = legalise_cell(cell.second.get()); @@ -448,6 +450,8 @@ bool legalise_relative_constraints(Context *ctx) { return ConstraintLegaliseWork int get_constraints_distance(const Context *ctx, const CellInfo *cell) { int dist = 0; + if (cell->isPseudo()) + return 0; if (cell->bel == BelId()) return 100000; Loc loc = ctx->getBelLocation(cell->bel); diff --git a/common/place/placer1.cc b/common/place/placer1.cc index a6ba3895..23264ce2 100644 --- a/common/place/placer1.cc +++ b/common/place/placer1.cc @@ -76,6 +76,8 @@ class SAPlacer pool<IdString> cell_types_in_use; for (auto &cell : ctx->cells) { + if (cell.second->isPseudo()) + continue; IdString cell_type = cell.second->type; cell_types_in_use.insert(cell_type); } @@ -120,7 +122,7 @@ class SAPlacer } for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); - if (ci->cluster == ClusterId()) + if (ci->isPseudo() || ci->cluster == ClusterId()) continue; cluster2cell[ci->cluster].push_back(ci); } @@ -145,6 +147,8 @@ class SAPlacer // Initial constraints placer for (auto &cell_entry : ctx->cells) { CellInfo *cell = cell_entry.second.get(); + if (cell->isPseudo()) + continue; auto loc = cell->attrs.find(ctx->id("BEL")); if (loc != cell->attrs.end()) { std::string loc_name = loc->second.as_string(); @@ -187,7 +191,7 @@ class SAPlacer for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); - if (ci->bel == BelId()) { + if (!ci->isPseudo() && (ci->bel == BelId())) { autoplaced.push_back(cell.second.get()); } } @@ -217,7 +221,7 @@ class SAPlacer } else { for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); - if (ci->belStrength > STRENGTH_STRONG) { + if (ci->isPseudo() || ci->belStrength > STRENGTH_STRONG) { continue; } else if (ci->cluster != ClusterId()) { if (ctx->getClusterRootCell(ci->cluster) == ci) @@ -353,6 +357,8 @@ class SAPlacer autoplaced.clear(); chain_basis.clear(); for (auto &cell : ctx->cells) { + if (cell.second->isPseudo()) + continue; if (cell.second->belStrength <= STRENGTH_STRONG && cell.second->cluster != ClusterId() && ctx->getClusterRootCell(cell.second->cluster) == cell.second.get()) chain_basis.push_back(cell.second.get()); @@ -814,7 +820,7 @@ class SAPlacer { BoundingBox bb; NPNR_ASSERT(net->driver.cell != nullptr); - Loc dloc = ctx->getBelLocation(net->driver.cell->bel); + Loc dloc = net->driver.cell->getLocation(); bb.x0 = dloc.x; bb.x1 = dloc.x; bb.y0 = dloc.y; @@ -824,9 +830,9 @@ class SAPlacer bb.ny0 = 1; bb.ny1 = 1; for (auto user : net->users) { - if (user.cell->bel == BelId()) + if (!user.cell->isPseudo() && user.cell->bel == BelId()) continue; - Loc uloc = ctx->getBelLocation(user.cell->bel); + Loc uloc = user.cell->getLocation(); if (bb.x0 == uloc.x) ++bb.nx0; else if (uloc.x < bb.x0) { @@ -1173,7 +1179,7 @@ class SAPlacer nets_by_tile.resize(max_x + 1, std::vector<dict<IdString, int>>(max_y + 1)); for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); - if (int(ci->ports.size()) > large_cell_thresh) + if (ci->isPseudo() || (int(ci->ports.size()) > large_cell_thresh)) continue; Loc loc = ctx->getBelLocation(ci->bel); auto &nbt = nets_by_tile.at(loc.x).at(loc.y); diff --git a/common/place/placer_heap.cc b/common/place/placer_heap.cc index 4c9ffb23..bd8cd37d 100644 --- a/common/place/placer_heap.cc +++ b/common/place/placer_heap.cc @@ -147,7 +147,7 @@ class HeAPPlacer tmg.setup(); for (auto &cell : ctx->cells) - if (cell.second->cluster != ClusterId()) + if (!cell.second->isPseudo() && cell.second->cluster != ClusterId()) cluster2cells[cell.second->cluster].push_back(cell.second.get()); } @@ -284,6 +284,8 @@ class HeAPPlacer // Save solution solution.clear(); for (auto &cell : ctx->cells) { + if (cell.second->isPseudo()) + continue; solution.emplace_back(cell.second.get(), cell.second->bel, cell.second->belStrength); } } else { @@ -312,6 +314,8 @@ class HeAPPlacer } for (auto &cell : ctx->cells) { + if (cell.second->isPseudo()) + continue; if (cell.second->bel == BelId()) log_error("Found unbound cell %s\n", cell.first.c_str(ctx)); if (ctx->getBoundBelCell(cell.second->bel) != cell.second.get()) @@ -411,7 +415,8 @@ class HeAPPlacer // Initial constraints placer for (auto &cell_entry : ctx->cells) { CellInfo *cell = cell_entry.second.get(); - + if (cell->isPseudo()) + continue; auto loc = cell->attrs.find(ctx->id("BEL")); if (loc != cell->attrs.end()) { std::string loc_name = loc->second.as_string(); @@ -461,6 +466,8 @@ class HeAPPlacer pool<IdString> cell_types_in_use; pool<BelBucketId> buckets_in_use; for (auto &cell : ctx->cells) { + if (cell.second->isPseudo()) + continue; IdString cell_type = cell.second->type; cell_types_in_use.insert(cell_type); BelBucketId bucket = ctx->getBelBucketForCellType(cell_type); @@ -527,6 +534,8 @@ class HeAPPlacer { pool<IdString> cell_types; for (const auto &cell : ctx->cells) { + if (cell.second->isPseudo()) + continue; cell_types.insert(cell.second->type); } @@ -551,6 +560,14 @@ class HeAPPlacer for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); + if (ci->isPseudo()) { + Loc loc = ci->pseudo_cell->getLocation(); + cell_locs[cell.first].x = loc.x; + cell_locs[cell.first].y = loc.y; + cell_locs[cell.first].locked = true; + cell_locs[cell.first].global = false; + continue; + } if (ci->bel != BelId()) { Loc loc = ctx->getBelLocation(ci->bel); cell_locs[cell.first].x = loc.x; @@ -627,8 +644,9 @@ class HeAPPlacer int row = 0; solve_cells.clear(); // First clear the udata of all cells - for (auto &cell : ctx->cells) + for (auto &cell : ctx->cells) { cell.second->udata = dont_solve; + } // Then update cells to be placed, which excludes cell children for (auto cell : place_cells) { if (buckets && !buckets->count(ctx->getBelBucketForCellType(cell->type))) |