From cd41c4001e68fd9e5741351d4640078e055b9c05 Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Mon, 1 Feb 2021 07:18:28 -0800 Subject: Add initial updates to FPGA interchange arch for BEL buckets. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- fpga_interchange/arch.cc | 7 ++ fpga_interchange/arch.h | 204 ++++++++++++++++++++++++++++++++++++ fpga_interchange/arch_pybindings.cc | 2 + fpga_interchange/arch_pybindings.h | 12 +++ fpga_interchange/archdefs.h | 22 ++++ 5 files changed, 247 insertions(+) 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 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 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 valid_cells; }); enum BELCategory { @@ -179,6 +182,17 @@ NPNR_PACKED_STRUCT(struct NodeInfoPOD { RelPtr tile_wires; }); +NPNR_PACKED_STRUCT(struct CellMapPOD { + // BEL bucket constids. + int32_t number_bel_buckets; + RelPtr bel_buckets; + + int32_t number_cells; + // Cell names supported in this arch. + RelPtr cell_names; + RelPtr cell_bel_buckets; +}); + NPNR_PACKED_STRUCT(struct ChipInfoPOD { RelPtr name; RelPtr generator; @@ -197,6 +211,11 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD { int32_t num_nodes; RelPtr nodes; + + RelPtr cell_map; + + int32_t number_bel_buckets; + RelPtr bel_buckets; }); /************************ End of chipdb section. ************************/ @@ -255,6 +274,62 @@ struct BelRange BelIterator end() const { return e; } }; +struct FilteredBelIterator +{ + std::function 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 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>::def_wrap(belpin_cls, "bel"); readonly_wrapper>::def_wrap(belpin_cls, "pin"); + typedef FilteredBelRange BelRangeForBelBucket; #include "arch_pybindings_shared.h" + WRAP_RANGE(m, BelBucket, conv_to_str); WRAP_RANGE(m, Bel, conv_to_str); WRAP_RANGE(m, Wire, conv_to_str); WRAP_RANGE(m, AllPip, conv_to_str); 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 } }; +template <> struct string_converter +{ + 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 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 return seed; } }; + +template <> struct hash +{ + std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX BelBucketId &bucket) const noexcept + { + std::size_t seed = 0; + boost::hash_combine(seed, hash()(bucket.name)); + return seed; + } +}; + } // namespace std -- cgit v1.2.3