Add initial updates to FPGA interchange arch for BEL buckets.
Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
parent
67dc19bb57
commit
cd41c4001e
@ -80,6 +80,13 @@ Arch::Arch(ArchArgs args) : args(args)
|
|||||||
for (int i = 0; i < chip_info->num_tiles; i++) {
|
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);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
@ -74,6 +74,7 @@ template <typename T> struct RelPtr
|
|||||||
NPNR_PACKED_STRUCT(struct BelInfoPOD {
|
NPNR_PACKED_STRUCT(struct BelInfoPOD {
|
||||||
int32_t name; // bel name (in site) constid
|
int32_t name; // bel name (in site) constid
|
||||||
int32_t type; // Type name constid
|
int32_t type; // Type name constid
|
||||||
|
int32_t bel_bucket; // BEL bucket constid.
|
||||||
|
|
||||||
int32_t num_bel_wires;
|
int32_t num_bel_wires;
|
||||||
RelPtr<int32_t> ports; // port name constid
|
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 site_variant; // some sites have alternative types
|
||||||
int16_t category;
|
int16_t category;
|
||||||
int16_t padding;
|
int16_t padding;
|
||||||
|
|
||||||
|
RelPtr<int8_t> valid_cells;
|
||||||
});
|
});
|
||||||
|
|
||||||
enum BELCategory {
|
enum BELCategory {
|
||||||
@ -179,6 +182,17 @@ NPNR_PACKED_STRUCT(struct NodeInfoPOD {
|
|||||||
RelPtr<TileWireRefPOD> tile_wires;
|
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 {
|
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
||||||
RelPtr<char> name;
|
RelPtr<char> name;
|
||||||
RelPtr<char> generator;
|
RelPtr<char> generator;
|
||||||
@ -197,6 +211,11 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
|||||||
|
|
||||||
int32_t num_nodes;
|
int32_t num_nodes;
|
||||||
RelPtr<NodeInfoPOD> nodes;
|
RelPtr<NodeInfoPOD> nodes;
|
||||||
|
|
||||||
|
RelPtr<CellMapPOD> cell_map;
|
||||||
|
|
||||||
|
int32_t number_bel_buckets;
|
||||||
|
RelPtr<int32_t> bel_buckets;
|
||||||
});
|
});
|
||||||
|
|
||||||
/************************ End of chipdb section. ************************/
|
/************************ End of chipdb section. ************************/
|
||||||
@ -255,6 +274,62 @@ struct BelRange
|
|||||||
BelIterator end() const { return e; }
|
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)
|
// Iterate over TileWires for a wire (will be more than one if nodal)
|
||||||
@ -553,6 +628,68 @@ struct BelPinRange
|
|||||||
BelPinIterator end() const { return e; }
|
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
|
struct ArchArgs
|
||||||
{
|
{
|
||||||
std::string chipdb;
|
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
|
// 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
|
// This is not intended for Bel type checks, but finer-grained constraints
|
||||||
// such as conflicting set/reset signals, etc
|
// such as conflicting set/reset signals, etc
|
||||||
|
@ -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::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");
|
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"
|
#include "arch_pybindings_shared.h"
|
||||||
|
|
||||||
|
WRAP_RANGE(m, BelBucket, conv_to_str<BelBucketId>);
|
||||||
WRAP_RANGE(m, Bel, conv_to_str<BelId>);
|
WRAP_RANGE(m, Bel, conv_to_str<BelId>);
|
||||||
WRAP_RANGE(m, Wire, conv_to_str<WireId>);
|
WRAP_RANGE(m, Wire, conv_to_str<WireId>);
|
||||||
WRAP_RANGE(m, AllPip, conv_to_str<PipId>);
|
WRAP_RANGE(m, AllPip, conv_to_str<PipId>);
|
||||||
|
@ -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>
|
template <> struct string_converter<BelPin>
|
||||||
{
|
{
|
||||||
BelPin from_str(Context *ctx, std::string name)
|
BelPin from_str(Context *ctx, std::string name)
|
||||||
|
@ -123,6 +123,17 @@ struct DecalId
|
|||||||
bool operator!=(const DecalId &other) const { return false; }
|
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
|
struct ArchNetInfo
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
@ -186,4 +197,15 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DecalId>
|
|||||||
return seed;
|
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
|
} // namespace std
|
||||||
|
Loading…
Reference in New Issue
Block a user