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++) {
|
||||
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 {
|
||||
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
|
||||
|
@ -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>);
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user