From 6a3eacddd60713d9c0d470d13a54a0c42f7d87c9 Mon Sep 17 00:00:00 2001 From: gatecat Date: Wed, 28 Apr 2021 14:49:26 +0100 Subject: Add default base implementation of cluster API Signed-off-by: gatecat --- common/arch_api.h | 2 +- common/base_arch.h | 93 +++++++++++++++++++++++++++++++++++++++++++++++ common/base_clusterinfo.h | 7 ++-- 3 files changed, 97 insertions(+), 5 deletions(-) (limited to 'common') diff --git a/common/arch_api.h b/common/arch_api.h index 76b78c62..f8e6d0ae 100644 --- a/common/arch_api.h +++ b/common/arch_api.h @@ -142,7 +142,7 @@ template struct ArchAPI : BaseCtx // Cluster methods virtual CellInfo *getClusterRootCell(ClusterId cluster) const = 0; virtual ArcBounds getClusterBounds(ClusterId cluster) const = 0; - virtual Loc getClusterOffset(ClusterId cluster, CellInfo *cell) const = 0; + virtual Loc getClusterOffset(CellInfo *cell) const = 0; virtual bool isClusterStrict(CellInfo *cell) const = 0; virtual bool getClusterPlacement(ClusterId cluster, BelId root_bel, std::vector> &placement) const = 0; diff --git a/common/base_arch.h b/common/base_arch.h index d4efe9ce..35500c1d 100644 --- a/common/base_arch.h +++ b/common/base_arch.h @@ -25,6 +25,7 @@ #include #include "arch_api.h" +#include "base_clusterinfo.h" #include "idstring.h" #include "nextpnr_types.h" @@ -80,6 +81,36 @@ typename std::enable_if::value, Tret>::type return_if_ma "respective range types are 'const std::vector&'"); } +// Default implementations of the clustering functions +template +typename std::enable_if::value, CellInfo *>::type get_cluster_root(const BaseCtx *ctx, + Tid cluster) +{ + return ctx->cells.at(cluster).get(); +} + +template +typename std::enable_if::value, CellInfo *>::type get_cluster_root(const BaseCtx *ctx, + Tid cluster) +{ + NPNR_ASSERT_FALSE("default implementation of getClusterRootCell requires ClusterId to be IdString"); +} + +// Executes the lambda with the base cluster data, only if the derivation works +template +typename std::enable_if::value, Tret>::type +if_using_basecluster(const Tcell *cell, Tfunc func) +{ + return func(static_cast(cell)); +} +template +typename std::enable_if::value, Tret>::type +if_using_basecluster(const Tcell *cell, Tfunc func) +{ + NPNR_ASSERT_FALSE( + "default implementation of cluster functions requires ArchCellInfo to derive from BaseClusterInfo"); +} + } // namespace // This contains the relevant range types for the default implementations of Arch functions @@ -343,6 +374,68 @@ template struct BaseArch : ArchAPI return return_if_match &, typename R::BucketBelRangeT>(bucket_bels.at(bucket)); } + // Cluster methods + virtual CellInfo *getClusterRootCell(ClusterId cluster) const override { return get_cluster_root(this, cluster); } + + virtual ArcBounds getClusterBounds(ClusterId cluster) const override + { + return if_using_basecluster(get_cluster_root(this, cluster), [](const BaseClusterInfo *cluster) { + ArcBounds bounds(0, 0, 0, 0); + for (auto child : cluster->constr_children) { + if_using_basecluster(child, [&](const BaseClusterInfo *child) { + bounds.x0 = std::min(bounds.x0, child->constr_x); + bounds.y0 = std::min(bounds.y0, child->constr_y); + bounds.x1 = std::max(bounds.x1, child->constr_x); + bounds.y1 = std::max(bounds.y1, child->constr_y); + }); + } + return bounds; + }); + } + + virtual Loc getClusterOffset(CellInfo *cell) const override + { + return if_using_basecluster(cell, + [](const BaseClusterInfo *c) { return Loc(c->constr_x, c->constr_y, 0); }); + } + + virtual bool isClusterStrict(CellInfo *cell) const override { return true; } + + virtual bool getClusterPlacement(ClusterId cluster, BelId root_bel, + std::vector> &placement) const override + { + CellInfo *root_cell = get_cluster_root(this, cluster); + return if_using_basecluster(root_cell, [&](const BaseClusterInfo *cluster) -> bool { + placement.clear(); + NPNR_ASSERT(root_bel != BelId()); + Loc root_loc = this->getBelLocation(root_bel); + + if (cluster->constr_abs_z) { + // Coerce root to absolute z constraint + root_loc.z = cluster->constr_z; + root_bel = this->getBelByLocation(root_loc); + if (root_bel == BelId() || !this->isValidBelForCellType(root_cell->type, root_bel)) + return false; + } + placement.emplace_back(root_cell, root_bel); + + for (auto child : cluster->constr_children) { + Loc child_loc = if_using_basecluster(child, [&](const BaseClusterInfo *child) { + Loc result; + result.x = root_loc.x + child->constr_x; + result.y = root_loc.y + child->constr_y; + result.z = child->constr_abs_z ? child->constr_z : (root_loc.z + child->constr_z); + return result; + }); + BelId child_bel = this->getBelByLocation(child_loc); + if (child_bel == BelId() || !this->isValidBelForCellType(child->type, root_bel)) + return false; + placement.emplace_back(child, child_bel); + } + return true; + }); + } + // Flow methods virtual void assignArchInfo() override{}; diff --git a/common/base_clusterinfo.h b/common/base_clusterinfo.h index a79f2686..32e6f87e 100644 --- a/common/base_clusterinfo.h +++ b/common/base_clusterinfo.h @@ -32,10 +32,9 @@ struct CellInfo; struct BaseClusterInfo { std::vector constr_children; - const int UNCONSTR = INT_MIN; - int constr_x = UNCONSTR; // this.x - parent.x - int constr_y = UNCONSTR; // this.y - parent.y - int constr_z = UNCONSTR; // this.z - parent.z + int constr_x = 0; // this.x - parent.x + int constr_y = 0; // this.y - parent.y + int constr_z = 0; // this.z - parent.z bool constr_abs_z = false; // parent.z := 0 }; -- cgit v1.2.3