aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-02-16 11:52:16 +0000
committergatecat <gatecat@ds0.me>2021-02-16 13:31:36 +0000
commitc7c13cd95f7a25b2c8932ca00ad667ffca381c70 (patch)
tree222496d567bd217e6958660a1e1153a1b273ca36 /ecp5
parent815b57b9e1f0c0a7176d146a29cef763bebf343f (diff)
downloadnextpnr-c7c13cd95f7a25b2c8932ca00ad667ffca381c70.tar.gz
nextpnr-c7c13cd95f7a25b2c8932ca00ad667ffca381c70.tar.bz2
nextpnr-c7c13cd95f7a25b2c8932ca00ad667ffca381c70.zip
Remove isValidBelForCell
This Arch API dates from when we were first working out how to implement placement validity checking, and in practice is little used by the core parts of placer1/HeAP and the Arch implementation involves a lot of duplication with isBelLocationValid. In the short term; placement validity checking is better served by the combination of checkBelAvail and isValidBelForCellType before placement; followed by isBelLocationValid after placement (potentially after moving/swapping multiple cells). Longer term, removing this API makes things a bit cleaner for a new validity checking API. Signed-off-by: gatecat <gatecat@ds0.me>
Diffstat (limited to 'ecp5')
-rw-r--r--ecp5/arch.h1
-rw-r--r--ecp5/arch_place.cc36
-rw-r--r--ecp5/arch_pybindings.cc3
-rw-r--r--ecp5/globals.cc50
4 files changed, 32 insertions, 58 deletions
diff --git a/ecp5/arch.h b/ecp5/arch.h
index d5edd88e..83928256 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -864,7 +864,6 @@ struct Arch : BaseArch<ArchRanges>
// -------------------------------------------------
// Placement validity checks
- bool isValidBelForCell(CellInfo *cell, BelId bel) const override;
bool isBelLocationValid(BelId bel) const override;
// Helper function for above
diff --git a/ecp5/arch_place.cc b/ecp5/arch_place.cc
index 668b3141..5565a01c 100644
--- a/ecp5/arch_place.cc
+++ b/ecp5/arch_place.cc
@@ -82,38 +82,14 @@ bool Arch::isBelLocationValid(BelId bel) const
return slices_compatible(bel_cells);
} else {
CellInfo *cell = getBoundBelCell(bel);
- if (cell == nullptr)
+ if (cell == nullptr) {
+ return true;
+ } else if (cell->type == id_DCUA || cell->type == id_EXTREFB || cell->type == id_PCSCLKDIV) {
+ return args.type != ArchArgs::LFE5U_25F && args.type != ArchArgs::LFE5U_45F &&
+ args.type != ArchArgs::LFE5U_85F;
+ } else {
return true;
- else
- return isValidBelForCell(cell, bel);
- }
-}
-
-bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
-{
- if (cell->type == id_TRELLIS_SLICE) {
- NPNR_ASSERT(getBelType(bel) == id_TRELLIS_SLICE);
-
- std::vector<const CellInfo *> bel_cells;
- Loc bel_loc = getBelLocation(bel);
-
- if (cell->sliceInfo.has_l6mux && ((bel_loc.z % 2) == 1))
- return false;
-
- for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
- CellInfo *cell_other = getBoundBelCell(bel_other);
- if (cell_other != nullptr && bel_other != bel) {
- bel_cells.push_back(cell_other);
- }
}
-
- bel_cells.push_back(cell);
- return slices_compatible(bel_cells);
- } else if (cell->type == id_DCUA || cell->type == id_EXTREFB || cell->type == id_PCSCLKDIV) {
- return args.type != ArchArgs::LFE5U_25F && args.type != ArchArgs::LFE5U_45F && args.type != ArchArgs::LFE5U_85F;
- } else {
- // other checks
- return true;
}
}
diff --git a/ecp5/arch_pybindings.cc b/ecp5/arch_pybindings.cc
index e1adbb46..5218ce36 100644
--- a/ecp5/arch_pybindings.cc
+++ b/ecp5/arch_pybindings.cc
@@ -44,9 +44,6 @@ void arch_wrap_python(py::module &m)
.def("place", &Context::place)
.def("route", &Context::route);
- fn_wrapper_2a<Context, decltype(&Context::isValidBelForCell), &Context::isValidBelForCell, pass_through<bool>,
- addr_and_unwrap<CellInfo>, conv_from_str<BelId>>::def_wrap(ctx_cls, "isValidBelForCell");
-
typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap;
typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap;
typedef std::unordered_map<IdString, IdString> AliasMap;
diff --git a/ecp5/globals.cc b/ecp5/globals.cc
index 1a0b7f2f..36bec64c 100644
--- a/ecp5/globals.cc
+++ b/ecp5/globals.cc
@@ -403,33 +403,35 @@ class Ecp5GlobalRouter
bool dedicated_routing = false;
for (auto bel : ctx->getBels()) {
if (ctx->getBelType(bel) == id_DCCA && ctx->checkBelAvail(bel)) {
- if (ctx->isValidBelForCell(dcc, bel)) {
- std::string belname = ctx->loc_info(bel)->bel_data[bel.index].name.get();
- if (belname.at(0) == 'D' && using_ce)
- continue; // don't allow DCCs with CE at center
- ctx->bindBel(bel, dcc, STRENGTH_LOCKED);
- wirelen_t wirelen = get_dcc_wirelen(dcc, dedicated_routing);
- if (wirelen < best_wirelen) {
- if (dedicated_routing) {
- best_bel_pclkcib = WireId();
- } else {
- bool found_pclkcib = false;
- for (WireId pclkcib : get_candidate_pclkcibs(bel)) {
- if (used_pclkcib.count(pclkcib))
- continue;
- found_pclkcib = true;
- best_bel_pclkcib = pclkcib;
- break;
- }
- if (!found_pclkcib)
- goto pclkcib_fail;
+ std::string belname = ctx->loc_info(bel)->bel_data[bel.index].name.get();
+ if (belname.at(0) == 'D' && using_ce)
+ continue; // don't allow DCCs with CE at center
+ ctx->bindBel(bel, dcc, STRENGTH_LOCKED);
+ if (!ctx->isBelLocationValid(bel)) {
+ ctx->unbindBel(bel);
+ continue;
+ }
+ wirelen_t wirelen = get_dcc_wirelen(dcc, dedicated_routing);
+ if (wirelen < best_wirelen) {
+ if (dedicated_routing) {
+ best_bel_pclkcib = WireId();
+ } else {
+ bool found_pclkcib = false;
+ for (WireId pclkcib : get_candidate_pclkcibs(bel)) {
+ if (used_pclkcib.count(pclkcib))
+ continue;
+ found_pclkcib = true;
+ best_bel_pclkcib = pclkcib;
+ break;
}
- best_bel = bel;
- best_wirelen = wirelen;
+ if (!found_pclkcib)
+ goto pclkcib_fail;
}
- pclkcib_fail:
- ctx->unbindBel(bel);
+ best_bel = bel;
+ best_wirelen = wirelen;
}
+ pclkcib_fail:
+ ctx->unbindBel(bel);
}
}
NPNR_ASSERT(best_bel != BelId());