aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2020-10-12 10:18:23 +0100
committerDavid Shah <dave@ds0.me>2020-11-30 08:45:27 +0000
commit12013b4c1f7a7fc653a06d1af8216680de468147 (patch)
treec23e5d347c0b8c5e785dba93744a40cb53eeb899
parente2de234ef17320773f089b9d807aaacbbcae45d2 (diff)
downloadnextpnr-12013b4c1f7a7fc653a06d1af8216680de468147.tar.gz
nextpnr-12013b4c1f7a7fc653a06d1af8216680de468147.tar.bz2
nextpnr-12013b4c1f7a7fc653a06d1af8216680de468147.zip
nexus: Lookup of package and IO pins
Signed-off-by: David Shah <dave@ds0.me>
-rw-r--r--nexus/arch.cc89
-rw-r--r--nexus/arch.h11
-rw-r--r--nexus/bba_version.inc2
-rw-r--r--nexus/pack.cc18
4 files changed, 119 insertions, 1 deletions
diff --git a/nexus/arch.cc b/nexus/arch.cc
index dfcf9510..f309c872 100644
--- a/nexus/arch.cc
+++ b/nexus/arch.cc
@@ -117,6 +117,22 @@ Arch::Arch(ArchArgs args) : args(args)
for (size_t i = 0; i < chip_info->num_tiles; i++) {
tileStatus[i].boundcells.resize(db->loctypes[chip_info->grid[i].loc_type].num_bels);
}
+ // Validate and set up package
+ package_idx = -1;
+ for (size_t i = 0; i < chip_info->num_packages; i++) {
+ if (package == chip_info->packages[i].short_name.get()) {
+ package_idx = i;
+ break;
+ }
+ }
+ if (package_idx == -1) {
+ std::string all_packages = "";
+ for (size_t i = 0; i < chip_info->num_packages; i++) {
+ all_packages += " ";
+ all_packages += chip_info->packages[i].short_name.get();
+ }
+ log_error("Unknown package '%s'. Available package options:%s\n", package.c_str(), all_packages.c_str());
+ }
}
// -----------------------------------------------------------------------
@@ -487,6 +503,79 @@ void Arch::set_cell_pinmux(CellInfo *cell, IdString pin, CellPinMux state)
// -----------------------------------------------------------------------
+const PadInfoPOD *Arch::get_pin_data(const std::string &pin) const
+{
+ for (size_t i = 0; i < chip_info->num_pads; i++) {
+ const PadInfoPOD *pad = &(chip_info->pads[i]);
+ if (pin == pad->pins[package_idx].get())
+ return pad;
+ }
+ return nullptr;
+}
+
+Loc Arch::get_pad_loc(const PadInfoPOD *pad) const
+{
+ Loc loc;
+ switch (pad->side) {
+ case PIO_LEFT:
+ loc.x = 0;
+ loc.y = pad->offset;
+ break;
+ case PIO_RIGHT:
+ loc.x = chip_info->width - 1;
+ loc.y = pad->offset;
+ break;
+ case PIO_TOP:
+ loc.x = pad->offset;
+ loc.y = 0;
+ break;
+ case PIO_BOTTOM:
+ loc.x = pad->offset;
+ loc.y = chip_info->height - 1;
+ }
+ loc.z = pad->pio_index;
+ return loc;
+}
+
+BelId Arch::get_pin_bel(const std::string &pin) const
+{
+ const PadInfoPOD *pad = get_pin_data(pin);
+ if (pad == nullptr)
+ return BelId();
+ return getBelByLocation(get_pad_loc(pad));
+}
+
+const PadInfoPOD *Arch::get_bel_pad(BelId bel) const
+{
+ Loc loc = getBelLocation(bel);
+ int side = -1, offset = -1;
+ // Convert (x, y) to (side, offset)
+ if (loc.x == 0) {
+ side = PIO_LEFT;
+ offset = loc.y;
+ } else if (loc.x == (chip_info->width - 1)) {
+ side = PIO_RIGHT;
+ offset = loc.y;
+ } else if (loc.y == 0) {
+ side = PIO_TOP;
+ offset = loc.x;
+ } else if (loc.y == (chip_info->height - 1)) {
+ side = PIO_BOTTOM;
+ offset = loc.x;
+ } else {
+ return nullptr;
+ }
+ // Lookup in the list of pads
+ for (size_t i = 0; i < chip_info->num_pads; i++) {
+ const PadInfoPOD *pad = &(chip_info->pads[i]);
+ if (pad->side == side && pad->offset == offset && pad->pio_index == loc.z)
+ return pad;
+ }
+ return nullptr;
+}
+
+// -----------------------------------------------------------------------
+
#ifdef WITH_HEAP
const std::string Arch::defaultPlacer = "heap";
#else
diff --git a/nexus/arch.h b/nexus/arch.h
index 89723853..886ee557 100644
--- a/nexus/arch.h
+++ b/nexus/arch.h
@@ -258,6 +258,8 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD {
uint16_t width;
uint16_t height;
uint32_t num_tiles;
+ uint32_t num_pads;
+ uint32_t num_packages;
RelPtr<GridLocationPOD> grid;
RelPtr<GlobalInfoPOD> globals;
RelPtr<PadInfoPOD> pads;
@@ -827,6 +829,8 @@ struct Arch : BaseCtx
const DatabasePOD *db;
const ChipInfoPOD *chip_info;
+ int package_idx;
+
// Binding states
struct LogicTileStatus
{
@@ -1430,6 +1434,13 @@ struct Arch : BaseCtx
// -------------------------------------------------
+ const PadInfoPOD *get_pin_data(const std::string &pin) const;
+ Loc get_pad_loc(const PadInfoPOD *pad) const;
+ BelId get_pin_bel(const std::string &pin) const;
+ const PadInfoPOD *get_bel_pad(BelId bel) const;
+
+ // -------------------------------------------------
+
// List of IO constraints, used by PDC parser
std::unordered_map<IdString, std::unordered_map<IdString, Property>> io_attr;
diff --git a/nexus/bba_version.inc b/nexus/bba_version.inc
index 7ed6ff82..1e8b3149 100644
--- a/nexus/bba_version.inc
+++ b/nexus/bba_version.inc
@@ -1 +1 @@
-5
+6
diff --git a/nexus/pack.cc b/nexus/pack.cc
index 602457f5..688d74ab 100644
--- a/nexus/pack.cc
+++ b/nexus/pack.cc
@@ -473,6 +473,23 @@ struct NexusPacker
}
}
+ void pack_io()
+ {
+ for (auto cell : sorted(ctx->cells)) {
+ CellInfo *ci = cell.second;
+ if (ci->type == id_SEIO33_CORE || ci->type == id_SEIO18_CORE) {
+ auto fnd_loc = ci->attrs.find(id_LOC);
+ if (fnd_loc == ci->attrs.end())
+ continue;
+ BelId bel = ctx->get_pin_bel(fnd_loc->second.as_string());
+ if (bel == BelId())
+ log_error("cannot constrain IO '%s', no PIO pin named '%s'\n", ctx->nameOf(ci),
+ fnd_loc->second.as_string().c_str());
+ ci->attrs[id_BEL] = ctx->getBelName(bel).str(ctx);
+ }
+ }
+ }
+
explicit NexusPacker(Context *ctx) : ctx(ctx) {}
void operator()()
@@ -480,6 +497,7 @@ struct NexusPacker
ctx->get_cell_pin_data(cell_db);
pack_ffs();
pack_luts();
+ pack_io();
}
};