aboutsummaryrefslogtreecommitdiffstats
path: root/common/place
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2022-06-23 18:48:31 +0100
committergatecat <gatecat@ds0.me>2022-07-08 14:30:57 +0200
commit09e388f453d9cf998391495349c88e5478b62e34 (patch)
tree004f2b14ed5a3b0584c4998d9f0a5598cc52ab28 /common/place
parent86396c41d64d2583ec1dffca4298e83d927f0762 (diff)
downloadnextpnr-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.cc12
-rw-r--r--common/place/parallel_refine.cc2
-rw-r--r--common/place/place_common.cc6
-rw-r--r--common/place/placer1.cc20
-rw-r--r--common/place/placer_heap.cc24
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)))