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 grid; RelPtr globals; RelPtr 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> 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(); } };