aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Rothman <537074+litghost@users.noreply.github.com>2021-02-01 07:18:28 -0800
committerKeith Rothman <537074+litghost@users.noreply.github.com>2021-02-04 16:38:33 -0800
commitcd41c4001e68fd9e5741351d4640078e055b9c05 (patch)
treed05d40ddeb18504b5ce669fec28717ea8b817b3c
parent67dc19bb579a1edcd1145f910e54c5baf2fa3cb6 (diff)
downloadnextpnr-cd41c4001e68fd9e5741351d4640078e055b9c05.tar.gz
nextpnr-cd41c4001e68fd9e5741351d4640078e055b9c05.tar.bz2
nextpnr-cd41c4001e68fd9e5741351d4640078e055b9c05.zip
Add initial updates to FPGA interchange arch for BEL buckets.
Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
-rw-r--r--fpga_interchange/arch.cc7
-rw-r--r--fpga_interchange/arch.h204
-rw-r--r--fpga_interchange/arch_pybindings.cc2
-rw-r--r--fpga_interchange/arch_pybindings.h12
-rw-r--r--fpga_interchange/archdefs.h22
5 files changed, 247 insertions, 0 deletions
diff --git a/fpga_interchange/arch.cc b/fpga_interchange/arch.cc
index 8fb5ffdb..d1540e82 100644
--- a/fpga_interchange/arch.cc
+++ b/fpga_interchange/arch.cc
@@ -80,6 +80,13 @@ Arch::Arch(ArchArgs args) : args(args)
for (int i = 0; i < chip_info->num_tiles; i++) {
tileStatus[i].boundcells.resize(chip_info->tile_types[chip_info->tiles[i].type].num_bels);
}
+
+ // Sanity check cell name ids.
+ const CellMapPOD & cell_map = *chip_info->cell_map;
+ int32_t first_cell_id = cell_map.cell_names[0];
+ for(size_t i = 0; i < cell_map.number_cells; ++i) {
+ log_assert(cell_map.cell_names[i] == i + first_cell_id);
+ }
}
// -----------------------------------------------------------------------
diff --git a/fpga_interchange/arch.h b/fpga_interchange/arch.h
index d29e8651..eb1e51c6 100644
--- a/fpga_interchange/arch.h
+++ b/fpga_interchange/arch.h
@@ -74,6 +74,7 @@ template <typename T> struct RelPtr
NPNR_PACKED_STRUCT(struct BelInfoPOD {
int32_t name; // bel name (in site) constid
int32_t type; // Type name constid
+ int32_t bel_bucket; // BEL bucket constid.
int32_t num_bel_wires;
RelPtr<int32_t> ports; // port name constid
@@ -84,6 +85,8 @@ NPNR_PACKED_STRUCT(struct BelInfoPOD {
int16_t site_variant; // some sites have alternative types
int16_t category;
int16_t padding;
+
+ RelPtr<int8_t> valid_cells;
});
enum BELCategory {
@@ -179,6 +182,17 @@ NPNR_PACKED_STRUCT(struct NodeInfoPOD {
RelPtr<TileWireRefPOD> tile_wires;
});
+NPNR_PACKED_STRUCT(struct CellMapPOD {
+ // BEL bucket constids.
+ int32_t number_bel_buckets;
+ RelPtr<int32_t> bel_buckets;
+
+ int32_t number_cells;
+ // Cell names supported in this arch.
+ RelPtr<int32_t> cell_names;
+ RelPtr<int32_t> cell_bel_buckets;
+});
+
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
RelPtr<char> name;
RelPtr<char> generator;
@@ -197,6 +211,11 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD {
int32_t num_nodes;
RelPtr<NodeInfoPOD> nodes;
+
+ RelPtr<CellMapPOD> cell_map;
+
+ int32_t number_bel_buckets;
+ RelPtr<int32_t> bel_buckets;
});
/************************ End of chipdb section. ************************/
@@ -255,6 +274,62 @@ struct BelRange
BelIterator end() const { return e; }
};
+struct FilteredBelIterator
+{
+ std::function<bool(BelId)> filter;
+ BelIterator b, e;
+
+ FilteredBelIterator operator++()
+ {
+ ++b;
+ while(b != e) {
+ if(filter(*b)) {
+ break;
+ }
+
+ ++b;
+ }
+ return *this;
+ }
+
+ bool operator!=(const FilteredBelIterator &other) const
+ {
+ NPNR_ASSERT(e == other.e);
+ return b != other.b;
+ }
+
+ bool operator==(const FilteredBelIterator &other) const
+ {
+ NPNR_ASSERT(e == other.e);
+ return b == other.b;
+ }
+
+ BelId operator*() const
+ {
+ return *b;
+ }
+};
+
+struct FilteredBelRange
+{
+ FilteredBelRange(BelIterator bel_b, BelIterator bel_e, std::function<bool(BelId)> filter) {
+ b.filter = filter;
+ b.b = bel_b;
+ b.e = bel_e;
+
+ if(b.b != b.e && !filter(*b.b)) {
+ ++b.b;
+ }
+
+ e.b = bel_e;
+ e.e = bel_e;
+ }
+
+ FilteredBelIterator b, e;
+ FilteredBelIterator begin() const { return b; }
+ FilteredBelIterator end() const { return e; }
+};
+
// -----------------------------------------------------------------------
// Iterate over TileWires for a wire (will be more than one if nodal)
@@ -553,6 +628,68 @@ struct BelPinRange
BelPinIterator end() const { return e; }
};
+struct IdStringIterator
+{
+ const int32_t *cursor;
+
+ void operator++()
+ {
+ cursor += 1;
+ }
+
+ bool operator!=(const IdStringIterator &other) const {
+ return cursor != other.cursor;
+ }
+
+ bool operator==(const IdStringIterator &other) const {
+ return cursor == other.cursor;
+ }
+
+ IdString operator*() const
+ {
+ return IdString(*cursor);
+ }
+};
+
+struct IdStringRange
+{
+ IdStringIterator b, e;
+ IdStringIterator begin() const { return b; }
+ IdStringIterator end() const { return e; }
+};
+
+struct BelBucketIterator
+{
+ IdStringIterator cursor;
+
+ void operator++()
+ {
+ ++cursor;
+ }
+
+ bool operator!=(const BelBucketIterator &other) const {
+ return cursor != other.cursor;
+ }
+
+ bool operator==(const BelBucketIterator &other) const {
+ return cursor == other.cursor;
+ }
+
+ BelBucketId operator*() const
+ {
+ BelBucketId bucket;
+ bucket.name = IdString(*cursor);
+ return bucket;
+ }
+};
+
+struct BelBucketRange
+{
+ BelBucketIterator b, e;
+ BelBucketIterator begin() const { return b; }
+ BelBucketIterator end() const { return e; }
+};
+
struct ArchArgs
{
std::string chipdb;
@@ -1081,6 +1218,73 @@ struct Arch : BaseCtx
// -------------------------------------------------
+ const BelBucketRange getBelBuckets() const {
+ BelBucketRange bel_bucket_range;
+ bel_bucket_range.b.cursor.cursor = &chip_info->bel_buckets[0];
+ bel_bucket_range.e.cursor.cursor = &chip_info->bel_buckets[chip_info->number_bel_buckets-1];
+ return bel_bucket_range;
+ }
+
+ BelBucketId getBelBucketForBel(BelId bel) const {
+ BelBucketId bel_bucket;
+ bel_bucket.name = IdString(locInfo(bel).bel_data[bel.index].bel_bucket);
+ return bel_bucket;
+ }
+
+ const IdStringRange getCellTypes() const {
+ const CellMapPOD & cell_map = *chip_info->cell_map;
+
+ IdStringRange id_range;
+ id_range.b.cursor = &cell_map.cell_names[0];
+ id_range.e.cursor = &cell_map.cell_names[cell_map.number_cells-1];
+
+ return id_range;
+ }
+
+ IdString getBelBucketName(BelBucketId bucket) const {
+ return bucket.name;
+ }
+
+ BelBucketId getBelBucketByName(IdString name) const {
+ for(BelBucketId bel_bucket : getBelBuckets()) {
+ if(bel_bucket.name == name) {
+ return bel_bucket;
+ }
+ }
+
+ NPNR_ASSERT_FALSE("Failed to find BEL bucket for name.");
+ return BelBucketId();
+ }
+
+ size_t getCellTypeIndex(IdString cell_type) const {
+ const CellMapPOD & cell_map = *chip_info->cell_map;
+ int cell_offset = cell_type.index - cell_map.cell_names[0];
+ NPNR_ASSERT(cell_type.index >= 0 && cell_type.index < cell_map.number_cells);
+
+ return cell_offset;
+ }
+
+ BelBucketId getBelBucketForCellType(IdString cell_type) const {
+ BelBucketId bucket;
+ const CellMapPOD & cell_map = *chip_info->cell_map;
+ bucket.name = cell_map.cell_bel_buckets[getCellTypeIndex(cell_type)];
+ return bucket;
+ }
+
+ FilteredBelRange getBelsInBucket(BelBucketId bucket) const {
+ BelRange range = getBels();
+ FilteredBelRange filtered_range(
+ range.begin(), range.end(), [this, bucket](BelId bel) {
+ return getBelBucketForBel(bel) == bucket;
+ });
+
+ return filtered_range;
+ }
+
+ bool isValidBelForCellType(IdString cell_type, BelId bel) const {
+ return locInfo(bel).bel_data[bel.index].valid_cells[getCellTypeIndex(cell_type)];
+ }
+
// Whether or not a given cell can be placed at a given Bel
// This is not intended for Bel type checks, but finer-grained constraints
// such as conflicting set/reset signals, etc
diff --git a/fpga_interchange/arch_pybindings.cc b/fpga_interchange/arch_pybindings.cc
index 1ad2286b..dee6a720 100644
--- a/fpga_interchange/arch_pybindings.cc
+++ b/fpga_interchange/arch_pybindings.cc
@@ -55,8 +55,10 @@ void arch_wrap_python(py::module &m)
readonly_wrapper<BelPin, decltype(&BelPin::bel), &BelPin::bel, conv_to_str<BelId>>::def_wrap(belpin_cls, "bel");
readonly_wrapper<BelPin, decltype(&BelPin::pin), &BelPin::pin, conv_to_str<IdString>>::def_wrap(belpin_cls, "pin");
+ typedef FilteredBelRange BelRangeForBelBucket;
#include "arch_pybindings_shared.h"
+ WRAP_RANGE(m, BelBucket, conv_to_str<BelBucketId>);
WRAP_RANGE(m, Bel, conv_to_str<BelId>);
WRAP_RANGE(m, Wire, conv_to_str<WireId>);
WRAP_RANGE(m, AllPip, conv_to_str<PipId>);
diff --git a/fpga_interchange/arch_pybindings.h b/fpga_interchange/arch_pybindings.h
index 0ce37906..b74a41a5 100644
--- a/fpga_interchange/arch_pybindings.h
+++ b/fpga_interchange/arch_pybindings.h
@@ -75,6 +75,18 @@ template <> struct string_converter<PipId>
}
};
+template <> struct string_converter<BelBucketId>
+{
+ BelBucketId from_str(Context *ctx, std::string name) { return ctx->getBelBucketByName(ctx->id(name)); }
+
+ std::string to_str(Context *ctx, BelBucketId id)
+ {
+ if (id == BelBucketId())
+ throw bad_wrap();
+ return ctx->getBelBucketName(id).str(ctx);
+ }
+};
+
template <> struct string_converter<BelPin>
{
BelPin from_str(Context *ctx, std::string name)
diff --git a/fpga_interchange/archdefs.h b/fpga_interchange/archdefs.h
index 744fa1d3..66d72f1c 100644
--- a/fpga_interchange/archdefs.h
+++ b/fpga_interchange/archdefs.h
@@ -123,6 +123,17 @@ struct DecalId
bool operator!=(const DecalId &other) const { return false; }
};
+struct BelBucketId {
+ IdString name;
+
+ bool operator==(const BelBucketId &other) const { return (name == other.name); }
+ bool operator!=(const BelBucketId &other) const { return (name != other.name); }
+ bool operator<(const BelBucketId &other) const
+ {
+ return name < other.name;
+ }
+};
+
struct ArchNetInfo
{
};
@@ -186,4 +197,15 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DecalId>
return seed;
}
};
+
+template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelBucketId>
+{
+ std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX BelBucketId &bucket) const noexcept
+ {
+ std::size_t seed = 0;
+ boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(bucket.name));
+ return seed;
+ }
+};
+
} // namespace std