diff --git a/machxo2/arch.cc b/machxo2/arch.cc index 9e638cbf..be6d81a1 100644 --- a/machxo2/arch.cc +++ b/machxo2/arch.cc @@ -201,27 +201,6 @@ BelId Arch::getBelByName(IdStringList name) const return BelId(); } -BelId Arch::getBelByLocation(Loc loc) const -{ - BelId ret; - - if (loc.x >= chip_info->width || loc.y >= chip_info->height) - return BelId(); - - ret.location.x = loc.x; - ret.location.y = loc.y; - - const TileTypePOD *loci = tile_info(ret); - for (int i = 0; i < loci->bel_data.ssize(); i++) { - if (loci->bel_data[i].z == loc.z) { - ret.index = i; - return ret; - } - } - - return BelId(); -} - BelRange Arch::getBelsByTile(int x, int y) const { BelRange br; @@ -239,24 +218,21 @@ BelRange Arch::getBelsByTile(int x, int y) const return br; } -bool Arch::getBelGlobalBuf(BelId bel) const { return false; } - WireId Arch::getBelPinWire(BelId bel, IdString pin) const { + WireId ret; + NPNR_ASSERT(bel != BelId()); for (auto &bw : tile_info(bel)->bel_data[bel.index].bel_wires) if (bw.port == pin.index) { - WireId ret; - ret.location.x = bw.rel_wire_loc.x; ret.location.y = bw.rel_wire_loc.y; ret.index = bw.wire_index; - - return ret; + break; } - return WireId(); + return ret; } PortType Arch::getBelPinType(BelId bel, IdString pin) const @@ -270,35 +246,6 @@ PortType Arch::getBelPinType(BelId bel, IdString pin) const return PORT_INOUT; } -std::vector Arch::getBelPins(BelId bel) const -{ - std::vector ret; - NPNR_ASSERT(bel != BelId()); - - for (auto &bw : tile_info(bel)->bel_data[bel.index].bel_wires) { - IdString id; - id.index = bw.port; - ret.push_back(id); - } - - return ret; -} - -// --------------------------------------------------------------- - -BelId Arch::getPackagePinBel(const std::string &pin) const -{ - for (auto &ppin : package_info->pin_data) { - if (ppin.name.get() == pin) { - BelId bel; - bel.location = ppin.abs_loc; - bel.index = ppin.bel_index; - return bel; - } - } - return BelId(); -} - // --------------------------------------------------------------- WireId Arch::getWireByName(IdStringList name) const @@ -362,6 +309,56 @@ IdStringList Arch::getPipName(PipId pip) const // --------------------------------------------------------------- +BelId Arch::get_package_pin_bel(const std::string &pin) const +{ + for (auto &ppin : package_info->pin_data) { + if (ppin.name.get() == pin) { + BelId bel; + bel.location = ppin.abs_loc; + bel.index = ppin.bel_index; + return bel; + } + } + return BelId(); +} + +std::vector Arch::getBelPins(BelId bel) const +{ + std::vector ret; + NPNR_ASSERT(bel != BelId()); + + for (auto &bw : tile_info(bel)->bel_data[bel.index].bel_wires) { + IdString id; + id.index = bw.port; + ret.push_back(id); + } + + return ret; +} + +BelId Arch::getBelByLocation(Loc loc) const +{ + BelId ret; + + if (loc.x >= chip_info->width || loc.y >= chip_info->height) + return BelId(); + + ret.location.x = loc.x; + ret.location.y = loc.y; + + const TileTypePOD *loci = tile_info(ret); + for (int i = 0; i < loci->bel_data.ssize(); i++) { + if (loci->bel_data[i].z == loc.z) { + ret.index = i; + return ret; + } + } + + return BelId(); +} + +// --------------------------------------------------------------- + delay_t Arch::estimateDelay(WireId src, WireId dst) const { // Taxicab distance multiplied by pipDelay (0.01) and fake wireDelay (0.01). @@ -370,6 +367,16 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const return (abs(dst.location.x - src.location.x) + abs(dst.location.y - src.location.y)) * (0.01 + 0.01); } +BoundingBox Arch::getRouteBoundingBox(WireId src, WireId dst) const +{ + BoundingBox bb; + bb.x0 = std::min(src.location.x, dst.location.x); + bb.y0 = std::min(src.location.y, dst.location.y); + bb.x1 = std::max(src.location.x, dst.location.x); + bb.y1 = std::max(src.location.y, dst.location.y); + return bb; +} + delay_t Arch::predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const { NPNR_UNUSED(src_pin); @@ -383,16 +390,6 @@ delay_t Arch::predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdStr (0.01 + 0.01); } -BoundingBox Arch::getRouteBoundingBox(WireId src, WireId dst) const -{ - BoundingBox bb; - bb.x0 = std::min(src.location.x, dst.location.x); - bb.y0 = std::min(src.location.y, dst.location.y); - bb.x1 = std::max(src.location.x, dst.location.x); - bb.y1 = std::max(src.location.y, dst.location.y); - return bb; -} - // --------------------------------------------------------------- bool Arch::place() @@ -508,6 +505,16 @@ DecalXY Arch::getPipDecal(PipId pip) const return decalxy; }; +DecalXY Arch::getGroupDecal(GroupId group) const +{ + DecalXY decalxy; + decalxy.decal.type = DecalId::TYPE_GROUP; + decalxy.decal.location = group.location; + decalxy.decal.z = group.type; + decalxy.decal.active = true; + return decalxy; +} + // --------------------------------------------------------------- const std::string Arch::defaultPlacer = "heap"; @@ -517,8 +524,6 @@ const std::vector Arch::availablePlacers = {"sa", "heap"}; const std::string Arch::defaultRouter = "router1"; const std::vector Arch::availableRouters = {"router1", "router2"}; -bool Arch::cells_compatible(const CellInfo **cells, int count) const { return false; } - std::vector> Arch::get_tiles_at_loc(int row, int col) { std::vector> ret; @@ -531,6 +536,72 @@ std::vector> Arch::get_tiles_at_loc(int row, // ----------------------------------------------------------------------- +GroupId Arch::getGroupByName(IdStringList name) const +{ + for (auto g : getGroups()) + if (getGroupName(g) == name) + return g; + return GroupId(); +} + +IdStringList Arch::getGroupName(GroupId group) const +{ + std::string suffix; + + switch (group.type) { + case GroupId::TYPE_SWITCHBOX: + suffix = "switchbox"; + break; + default: + return IdStringList(); + } + + std::array ids{x_ids.at(group.location.x), y_ids.at(group.location.y), id(suffix)}; + return IdStringList(ids); +} + +std::vector Arch::getGroups() const +{ + std::vector ret; + + for (int y = 1; y < chip_info->height - 1; y++) { + for (int x = 1; x < chip_info->width - 1; x++) { + GroupId group; + group.type = GroupId::TYPE_SWITCHBOX; + group.location.x = x; + group.location.y = y; + ret.push_back(group); + } + } + return ret; +} + +std::vector Arch::getGroupBels(GroupId group) const +{ + std::vector ret; + return ret; +} + +std::vector Arch::getGroupWires(GroupId group) const +{ + std::vector ret; + return ret; +} + +std::vector Arch::getGroupPips(GroupId group) const +{ + std::vector ret; + return ret; +} + +std::vector Arch::getGroupGroups(GroupId group) const +{ + std::vector ret; + return ret; +} + +// ----------------------------------------------------------------------- + std::vector> Arch::getWireAttrs(WireId wire) const { std::vector> ret; diff --git a/machxo2/arch.h b/machxo2/arch.h index 2be987b7..16150168 100644 --- a/machxo2/arch.h +++ b/machxo2/arch.h @@ -149,8 +149,6 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD { /************************ End of chipdb section. ************************/ -// Iterators -// Iterate over Bels across tiles. struct BelIterator { const ChipInfoPOD *chip; @@ -200,7 +198,8 @@ struct BelRange BelIterator end() const { return e; } }; -// Iterate over Downstream/Upstream Bels for a Wire. +// ----------------------------------------------------------------------- + struct BelPinIterator { const BelPortPOD *ptr = nullptr; @@ -225,7 +224,8 @@ struct BelPinRange BelPinIterator end() const { return e; } }; -// Iterator over Wires across tiles. +// ----------------------------------------------------------------------- + struct WireIterator { const ChipInfoPOD *chip; @@ -275,7 +275,8 @@ struct WireRange WireIterator end() const { return e; } }; -// Iterator over Pips across tiles. +// ----------------------------------------------------------------------- + struct AllPipIterator { const ChipInfoPOD *chip; @@ -325,7 +326,8 @@ struct AllPipRange AllPipIterator end() const { return e; } }; -// Iterate over Downstream/Upstream Pips for a Wire. +// ----------------------------------------------------------------------- + struct PipIterator { @@ -383,11 +385,6 @@ struct Arch : BaseArch mutable dict pip_by_name; - // fast access to X and Y IdStrings for building object names - std::vector x_ids, y_ids; - // inverse of the above for name->object mapping - dict id_to_x, id_to_y; - enum class LutPermRule { NONE, @@ -397,6 +394,9 @@ struct Arch : BaseArch std::vector lutperm_allowed; bool disable_router_lutperm = false; + // For fast, incremental validity checking of split SLICE + + // BEL z-position lookup, x-ored with (index in tile) << 2 enum LogicBELType { BEL_COMB = 0, @@ -427,8 +427,6 @@ struct Arch : BaseArch ~TileStatus() { delete lts; } }; - mutable std::vector tile_status; - // faster replacements for base_pip2net, base_wire2net // indexed by get_pip_vecidx() std::vector pip2net; @@ -440,53 +438,49 @@ struct Arch : BaseArch std::vector pip_tile_vecidx; std::vector wire_tile_vecidx; - // Helpers - template const TileTypePOD *tile_info(Id &id) const - { - return &(chip_info->tiles[id.location.y * chip_info->width + id.location.x]); - } + // fast access to X and Y IdStrings for building object names + std::vector x_ids, y_ids; + // inverse of the above for name->object mapping + dict id_to_x, id_to_y; - int get_bel_flat_index(BelId bel) const - { - return (bel.location.y * chip_info->width + bel.location.x) * max_loc_bels + bel.index; - } - - template inline int tile_index(Id id) const - { - return id.location.y * chip_info->width + id.location.x; - } - - // --------------------------------------------------------------- - // Common Arch API. Every arch must provide the following methods. - - // General ArchArgs args; Arch(ArchArgs args); static void list_devices(); std::string getChipName() const override; - // Extra helper std::string get_full_chip_name() const; IdString archId() const override { return id_machxo2; } ArchArgs archArgs() const override { return args; } IdString archArgsToId(ArchArgs args) const override; - static const int max_loc_bels = 20; + // ------------------------------------------------- - int getGridDimX() const override { return chip_info->width; } - int getGridDimY() const override { return chip_info->height; } - int getTileBelDimZ(int x, int y) const override { return max_loc_bels; } + static const int max_loc_bels = 32; + + int getGridDimX() const override { return chip_info->width; }; + int getGridDimY() const override { return chip_info->height; }; + int getTileBelDimZ(int, int) const override { return max_loc_bels; }; // TODO: Make more precise? The CENTER MUX having config bits across // tiles can complicate this? - int getTilePipDimZ(int x, int y) const override { return 2; } - + int getTilePipDimZ(int, int) const override { return 2; }; char getNameDelimiter() const override { return '/'; } - // Bels + // ------------------------------------------------- + BelId getBelByName(IdStringList name) const override; + template const TileTypePOD *tile_info(Id &id) const + { + return &(chip_info->tiles[id.location.y * chip_info->width + id.location.x]); + } + + template inline int tile_index(Id id) const + { + return id.location.y * chip_info->width + id.location.x; + } + IdStringList getBelName(BelId bel) const override { NPNR_ASSERT(bel != BelId()); @@ -563,7 +557,8 @@ struct Arch : BaseArch BelId getBelByLocation(Loc loc) const override; BelRange getBelsByTile(int x, int y) const override; - bool getBelGlobalBuf(BelId bel) const override; + + bool getBelGlobalBuf(BelId bel) const override { return false; } bool checkBelAvail(BelId bel) const override { @@ -608,13 +603,22 @@ struct Arch : BaseArch } WireId getBelPinWire(BelId bel, IdString pin) const override; - PortType getBelPinType(BelId bel, IdString pin) const override; + + BelPinRange getWireBelPins(WireId wire) const override + { + BelPinRange range; + NPNR_ASSERT(wire != WireId()); + range.b.ptr = tile_info(wire)->wire_data[wire.index].bel_pins.begin(); + range.b.wire_loc = wire.location; + range.e.ptr = tile_info(wire)->wire_data[wire.index].bel_pins.end(); + range.e.wire_loc = wire.location; + return range; + } + std::vector getBelPins(BelId bel) const override; - // Package - BelId getPackagePinBel(const std::string &pin) const; + // ------------------------------------------------- - // Wires WireId getWireByName(IdStringList name) const override; IdStringList getWireName(WireId wire) const override @@ -694,17 +698,6 @@ struct Arch : BaseArch return range; } - BelPinRange getWireBelPins(WireId wire) const override - { - BelPinRange range; - NPNR_ASSERT(wire != WireId()); - range.b.ptr = tile_info(wire)->wire_data[wire.index].bel_pins.begin(); - range.b.wire_loc = wire.location; - range.e.ptr = tile_info(wire)->wire_data[wire.index].bel_pins.end(); - range.e.wire_loc = wire.location; - return range; - } - IdString get_wire_basename(WireId wire) const { return id(tile_info(wire)->wire_data[wire.index].name.get()); } WireId get_wire_by_loc_basename(Location loc, std::string basename) const @@ -720,7 +713,8 @@ struct Arch : BaseArch return WireId(); } - // Pips + // ------------------------------------------------- + PipId getPipByName(IdStringList name) const override; IdStringList getPipName(PipId pip) const override; @@ -809,18 +803,6 @@ struct Arch : BaseArch return range; } - Loc getPipLocation(PipId pip) const override - { - Loc loc; - loc.x = pip.location.x; - loc.y = pip.location.y; - - // FIXME: Some Pip's config bits span across tiles. Will Z - // be affected by this? - loc.z = 0; - return loc; - } - WireId getPipSrcWire(PipId pip) const override { WireId wire; @@ -863,9 +845,6 @@ struct Arch : BaseArch return range; } - // Extra Pip helpers. - int8_t get_pip_class(PipId pip) const { return tile_info(pip)->pip_data[pip.index].pip_type; } - std::string get_pip_tilename(PipId pip) const { auto &tileloc = chip_info->tile_info[pip.location.y * chip_info->width + pip.location.x]; @@ -881,32 +860,65 @@ struct Arch : BaseArch return chip_info->tiletype_names[tile_info(pip)->pip_data[pip.index].tile_type].get(); } - // Delay + Loc getPipLocation(PipId pip) const override + { + Loc loc; + loc.x = pip.location.x; + loc.y = pip.location.y; + loc.z = 0; + return loc; + } + + int8_t get_pip_class(PipId pip) const { return tile_info(pip)->pip_data[pip.index].pip_type; } + + BelId get_package_pin_bel(const std::string &pin) const; + //std::string get_bel_package_pin(BelId bel) const; + //int get_pio_bel_bank(BelId bel) const; + // For getting GCLK, PLL, Vref, etc, pins + //std::string get_pio_function_name(BelId bel) const; + //BelId get_pio_by_function_name(const std::string &name) const; + + PortType getBelPinType(BelId bel, IdString pin) const override; + + // ------------------------------------------------- + + GroupId getGroupByName(IdStringList name) const override; + IdStringList getGroupName(GroupId group) const override; + std::vector getGroups() const override; + std::vector getGroupBels(GroupId group) const override; + std::vector getGroupWires(GroupId group) const override; + std::vector getGroupPips(GroupId group) const override; + std::vector getGroupGroups(GroupId group) const override; + + // ------------------------------------------------- + delay_t estimateDelay(WireId src, WireId dst) const override; + BoundingBox getRouteBoundingBox(WireId src, WireId dst) const override; delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const override; delay_t getDelayEpsilon() const override { return 0.001; } delay_t getRipupDelayPenalty() const override { return 0.015; } float getDelayNS(delay_t v) const override { return v; } - delay_t getDelayFromNS(float ns) const override { return ns; } - uint32_t getDelayChecksum(delay_t v) const override { return v; } + //bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override; - BoundingBox getRouteBoundingBox(WireId src, WireId dst) const override; + // ------------------------------------------------- - // Flow bool pack() override; bool place() override; bool route() override; - // Graphics + // ------------------------------------------------- + std::vector getDecalGraphics(DecalId decal) const override; DecalXY getBelDecal(BelId bel) const override; DecalXY getWireDecal(WireId wire) const override; DecalXY getPipDecal(PipId pip) const override; + DecalXY getGroupDecal(GroupId group) const override; - // Placer + // ------------------------------------------------- + // Placement validity checks bool isBelLocationValid(BelId bel, bool explain_invalid = false) const override; // Helper function for above @@ -915,15 +927,6 @@ struct Arch : BaseArch void assign_arch_info_for_cell(CellInfo *ci); void assignArchInfo() override; - static const std::string defaultPlacer; - static const std::vector availablePlacers; - static const std::string defaultRouter; - static const std::vector availableRouters; - - // --------------------------------------------------------------- - // Internal usage - bool cells_compatible(const CellInfo **cells, int count) const; - std::vector> get_tiles_at_loc(int row, int col); std::string get_tile_by_type_loc(int row, int col, std::string type) const { @@ -956,6 +959,16 @@ struct Arch : BaseArch } NPNR_ASSERT_FALSE_STR("no tile with type " + type); } + + static const std::string defaultPlacer; + static const std::vector availablePlacers; + static const std::string defaultRouter; + static const std::vector availableRouters; + + mutable std::vector tile_status; + + // ------------------------------------------------- + }; NEXTPNR_NAMESPACE_END diff --git a/machxo2/archdefs.h b/machxo2/archdefs.h index 4809324a..0152b7ac 100644 --- a/machxo2/archdefs.h +++ b/machxo2/archdefs.h @@ -30,6 +30,8 @@ NEXTPNR_NAMESPACE_BEGIN typedef float delay_t; +// ----------------------------------------------------------------------- + // https://bugreports.qt.io/browse/QTBUG-80789 #ifndef Q_MOC_RUN @@ -107,6 +109,22 @@ struct PipId unsigned int hash() const { return mkhash(location.hash(), index); } }; +typedef IdString BelBucketId; + +struct GroupId +{ + enum : int8_t + { + TYPE_NONE, + TYPE_SWITCHBOX + } type = TYPE_NONE; + Location location; + + bool operator==(const GroupId &other) const { return (type == other.type) && (location == other.location); } + bool operator!=(const GroupId &other) const { return (type != other.type) || (location != other.location); } + unsigned int hash() const { return mkhash(location.hash(), int(type)); } +}; + struct DecalId { enum @@ -131,14 +149,13 @@ struct DecalId unsigned int hash() const { return mkhash(location.hash(), mkhash(z, int(type))); } }; -typedef IdString GroupId; -typedef IdString BelBucketId; -typedef IdString ClusterId; - struct ArchNetInfo { }; +typedef IdString ClusterId; + +struct CellInfo; struct NetInfo; struct ArchCellInfo : BaseClusterInfo @@ -197,5 +214,4 @@ struct ArchCellInfo : BaseClusterInfo }; NEXTPNR_NAMESPACE_END - #endif /* MACHXO2_ARCHDEFS_H */ diff --git a/machxo2/pack.cc b/machxo2/pack.cc index b6aa8be6..78becc18 100644 --- a/machxo2/pack.cc +++ b/machxo2/pack.cc @@ -381,7 +381,7 @@ class Ecp5Packer auto loc_attr = trio->attrs.find(id_LOC); if (loc_attr != trio->attrs.end()) { std::string pin = loc_attr->second.as_string(); - BelId pinBel = ctx->getPackagePinBel(pin); + BelId pinBel = ctx->get_package_pin_bel(pin); if (pinBel == BelId()) { log_error("IO pin '%s' constrained to pin '%s', which does not exist for package '%s'.\n", trio->name.c_str(ctx), pin.c_str(), ctx->package_name);