diff --git a/common/archcheck.cc b/common/archcheck.cc index 3c4c3133..1c5d57a0 100644 --- a/common/archcheck.cc +++ b/common/archcheck.cc @@ -51,6 +51,16 @@ void archcheck_names(const Context *ctx) log_error("wire != wire2, name = %s\n", name.c_str(ctx)); } } + + log_info("Checking partition names..\n"); + for(PartitionId partition : ctx->getPartitions()) { + IdString name = ctx->getPartitionName(partition); + PartitionId partition2 = ctx->getPartitionByName(name); + if (partition != partition2) { + log_error("partition != partition2, name = %s\n", name.c_str(ctx)); + } + } + #ifndef ARCH_ECP5 log_info("Checking pip names..\n"); for (PipId pip : ctx->getPips()) { @@ -187,6 +197,59 @@ void archcheck_conn(const Context *ctx) } } +void archcheck_partitions(const Context *ctx) +{ + log_info("Checking partition data.\n"); + + // Partitions should be subsets of BELs that form an exact cover. + // In particular that means cell types in a partition should only be + // placable in that partition. + for(PartitionId partition : ctx->getPartitions()) { + + // Find out which cell types are in this partition. + std::unordered_set cell_types_in_partition; + for(IdString cell_type : ctx->getCellTypes()) { + if(ctx->getPartitionForCellType(cell_type) == partition) { + cell_types_in_partition.insert(cell_type); + } + } + + // Make sure that all cell types in this partition have at least one + // BelId they can be placed at. + std::unordered_set cell_types_unused; + + std::unordered_set bels_in_partition; + for(BelId bel : ctx->getBelsForPartition(partition)) { + PartitionId partition2 = ctx->getPartitionForBel(bel); + log_assert(partition == partition2); + + bels_in_partition.insert(bel); + + // Check to see if a cell type not in this partition can be + // placed at a BEL in this partition. + for(IdString cell_type : ctx->getCellTypes()) { + if(ctx->getPartitionForCellType(cell_type) == partition) { + if(ctx->isValidBelForCellType(cell_type, bel)) { + cell_types_unused.erase(cell_type); + } + } else { + log_assert(!ctx->isValidBelForCellType(cell_type, bel)); + } + } + } + + // Verify that any BEL not in this partition reports a different + // partition. + for(BelId bel : ctx->getBels()) { + if(ctx->getPartitionForBel(bel) != partition) { + log_assert(bels_in_partition.count(bel) == 0); + } + } + + log_assert(cell_types_unused.empty()); + } +} + } // namespace NEXTPNR_NAMESPACE_BEGIN @@ -199,6 +262,7 @@ void Context::archcheck() const archcheck_names(this); archcheck_locs(this); archcheck_conn(this); + archcheck_partitions(this); } NEXTPNR_NAMESPACE_END diff --git a/docs/archapi.md b/docs/archapi.md index 3a0efcce..53132bd9 100644 --- a/docs/archapi.md +++ b/docs/archapi.md @@ -88,6 +88,14 @@ Get Z dimension for the specified tile for bels. All bels with at specified X an Get Z dimension for the specified tile for pips. All pips with at specified X and Y coordinates must have a Z coordinate in the range `0 .. getTileDimZ(X,Y)-1` (inclusive). +Cell Methods +----------- + +### const\_range\ getCellTypes() const + +Get list of cell types that this architecture accepts. + + Bel Methods ----------- @@ -478,8 +486,8 @@ information for all edges. `index` must be in [0, clockInfoCount), behaviour is Partition Methods ----------------- -Partitions are used by analytic placement to seperate types of BELs during -placement. Typical partitions are: +Partitions are subsets of BelIds and cell types used by analytic placement to +seperate types of BELs during placement. Typical partitions are: - All LUT BELs - All FF BELs - All multipliers BELs @@ -487,7 +495,8 @@ placement. Typical partitions are: - etc. The general rule here is to include all BELs that are roughly interchangable -during placement. +during placement. Partitions should form an exact cover over all BelIds and +cell types. ### const\_range\ getPartitions() const @@ -497,8 +506,16 @@ Return a list of all partitions on the device. Return the name of the partition. +### PartitionId getPartitionByName(IdString partition\_name) const + +Return the partition for the specified partition name. + ### PartitionId getPartitionForBel(BelId bel) const +Returns the partition for a particular BEL. + +### PartitionId getPartitionForCell(IdString cell\_type) const + Returns the partition for a particular cell type. ### const\_range\ getBelsForPartition(PartitionId partition) const diff --git a/generic/arch.h b/generic/arch.h index abe7ff7d..b1af5175 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -271,6 +271,34 @@ struct Arch : BaseCtx bool place(); bool route(); + std::vector getCellTypes() const { + return {}; + } + + std::vector getPartitions() const { + return {}; + } + + IdString getPartitionName(PartitionId partition) const { + return partition; + } + + PartitionId getPartitionByName(IdString partition) const { + return partition; + } + + PartitionId getPartitionForBel(BelId bel) const { + return getBelType(bel); + } + + PartitionId getPartitionForCellType(IdString cell_type) const { + return cell_type; + } + + std::vector getBelsForPartition(PartitionId partition) const { + return {}; + } + const std::vector &getDecalGraphics(DecalId decal) const; DecalXY getBelDecal(BelId bel) const; DecalXY getWireDecal(WireId wire) const; diff --git a/generic/archdefs.h b/generic/archdefs.h index 978c9c9b..cb78249a 100644 --- a/generic/archdefs.h +++ b/generic/archdefs.h @@ -51,6 +51,7 @@ typedef IdString WireId; typedef IdString PipId; typedef IdString GroupId; typedef IdString DecalId; +typedef IdString PartitionId; struct ArchNetInfo {