aboutsummaryrefslogtreecommitdiffstats
path: root/fpga_interchange/arch.h
diff options
context:
space:
mode:
Diffstat (limited to 'fpga_interchange/arch.h')
-rw-r--r--fpga_interchange/arch.h204
1 files changed, 204 insertions, 0 deletions
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