diff --git a/common/nextpnr.h b/common/nextpnr.h index 09bd1554..a162b85c 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -271,6 +271,7 @@ struct BaseCtx std::unordered_set belUiReload; std::unordered_set wireUiReload; std::unordered_set pipUiReload; + std::unordered_set groupUiReload; void refreshUi() { @@ -296,6 +297,11 @@ struct BaseCtx { pipUiReload.insert(pip); } + + void refreshUiGroup(GroupId group) + { + groupUiReload.insert(group); + } }; NEXTPNR_NAMESPACE_END @@ -368,6 +374,19 @@ struct Context : Arch return ret; } + NPNR_DEPRECATED std::vector getGroupGraphics(GroupId group) const { + std::vector ret; + DecalXY decalxy = getGroupDecal(group); + ret = getDecalGraphics(decalxy.decal); + for (auto &it : ret) { + it.x1 += decalxy.x; + it.x2 += decalxy.x; + it.y1 += decalxy.y; + it.y2 += decalxy.y; + } + return ret; + } + // -------------------------------------------------------------- // provided by router1.cc diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 7383e0e7..286151d8 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -317,6 +317,8 @@ DecalXY Arch::getWireDecal(WireId wire) const { return {}; } DecalXY Arch::getPipDecal(PipId pip) const { return {}; }; +DecalXY Arch::getGroupDecal(PipId pip) const { return {}; }; + // ----------------------------------------------------------------------- bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const { return true; } diff --git a/ecp5/arch.h b/ecp5/arch.h index 5f01c8c8..bbc7c561 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -711,6 +711,16 @@ struct Arch : BaseCtx // ------------------------------------------------- + GroupId getGroupByName(IdString name) const { return GroupId(); } + IdString getGroupName(GroupId group) const { return IdString(); } + std::vector getGroups() const { return std::vector(); } + std::vector getGroupBels(GroupId group) const { return std::vector(); } + std::vector getGroupWires(GroupId group) const { return std::vector(); } + std::vector getGroupPips(GroupId group) const { return std::vector(); } + std::vector getGroupGroups(GroupId group) const { return std::vector(); } + + // ------------------------------------------------- + void estimatePosition(BelId bel, int &x, int &y, bool &gb) const; delay_t estimateDelay(WireId src, WireId dst) const; delay_t getDelayEpsilon() const { return 20; } @@ -731,6 +741,7 @@ struct Arch : BaseCtx DecalXY getBelDecal(BelId bel) const; DecalXY getWireDecal(WireId wire) const; DecalXY getPipDecal(PipId pip) const; + DecalXY getGroupDecal(GroupId group) const; // ------------------------------------------------- diff --git a/ecp5/archdefs.h b/ecp5/archdefs.h index 79b20619..797db5f7 100644 --- a/ecp5/archdefs.h +++ b/ecp5/archdefs.h @@ -105,11 +105,22 @@ struct PipId bool operator!=(const PipId &other) const { return index != other.index || location != other.location; } }; +struct GroupId +{ + int32_t index = -1; + + bool operator==(const GroupId &other) const { return index == other.index; } + bool operator!=(const GroupId &other) const { return index != other.index; } +}; + struct DecalId { char type = 0; // Bel/Wire/Pip/Frame (b/w/p/f) Location location; uint32_t z = 0; + + bool operator==(const DecalId &other) const { return type == other.type && location == other.location && z == other.z; } + bool operator!=(const DecalId &other) const { return type != other.type || location != other.location || z != other.z; } }; NEXTPNR_NAMESPACE_END @@ -155,6 +166,14 @@ template <> struct hash } }; +template <> struct hash +{ + std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX GroupId &group) const noexcept + { + return std::hash()(group.index); + } +}; + template <> struct hash { std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX DecalId &decal) const noexcept diff --git a/generic/arch.cc b/generic/arch.cc index 60874e1e..1e1434d3 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -109,6 +109,26 @@ void Arch::addBelInout(IdString bel, IdString name, IdString wire) wires.at(wire).downhill_bel_pins.push_back(BelPin{bel, name}); } +void Arch::addGroupBel(IdString group, IdString bel) +{ + groups[group].bels.push_back(bel); +} + +void Arch::addGroupWire(IdString group, IdString wire) +{ + groups[group].wires.push_back(wire); +} + +void Arch::addGroupPip(IdString group, IdString pip) +{ + groups[group].pips.push_back(pip); +} + +void Arch::addGroupGroup(IdString group, IdString grp) +{ + groups[group].groups.push_back(grp); +} + void Arch::addDecalGraphic(DecalId decal, const GraphicElement &graphic) { decal_graphics[decal].push_back(graphic); @@ -139,6 +159,12 @@ void Arch::setBelDecal(BelId bel, DecalXY decalxy) refreshUiBel(bel); } +void Arch::setGroupDecal(GroupId group, DecalXY decalxy) +{ + groups[group].decalxy = decalxy; + refreshUiGroup(group); +} + // --------------------------------------------------------------- Arch::Arch(ArchArgs) {} @@ -300,6 +326,27 @@ const std::vector &Arch::getWireAliases(WireId wire) const { return wires // --------------------------------------------------------------- +GroupId Arch::getGroupByName(IdString name) const { return name; } + +IdString Arch::getGroupName(GroupId group) const { return group; } + +std::vector Arch::getGroups() const { + std::vector ret; + for (auto &it : groups) + ret.push_back(it.first); + return ret; +} + +const std::vector &Arch::getGroupBels(GroupId group) const { return groups.at(group).bels; } + +const std::vector &Arch::getGroupWires(GroupId group) const { return groups.at(group).wires; } + +const std::vector &Arch::getGroupPips(GroupId group) const { return groups.at(group).pips; } + +const std::vector &Arch::getGroupGroups(GroupId group) const { return groups.at(group).groups; } + +// --------------------------------------------------------------- + void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const { x = bels.at(bel).grid_x; @@ -330,7 +377,6 @@ bool Arch::route() // --------------------------------------------------------------- - const std::vector &Arch::getDecalGraphics(DecalId decal) const { return decal_graphics.at(decal); } DecalXY Arch::getFrameDecal() const { return frame_decalxy; } @@ -341,6 +387,8 @@ DecalXY Arch::getWireDecal(WireId wire) const { return wires.at(wire).decalxy; } DecalXY Arch::getPipDecal(PipId pip) const { return pips.at(pip).decalxy; } +DecalXY Arch::getGroupDecal(GroupId group) const { return groups.at(group).decalxy; } + // --------------------------------------------------------------- bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, delay_t &delay) const diff --git a/generic/arch.h b/generic/arch.h index 85f469f9..f6243404 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -63,6 +63,16 @@ struct BelInfo bool gb; }; +struct GroupInfo +{ + IdString name; + std::vector bels; + std::vector wires; + std::vector pips; + std::vector groups; + DecalXY decalxy; +}; + struct Arch : BaseCtx { std::string chipName; @@ -70,6 +80,7 @@ struct Arch : BaseCtx std::unordered_map wires; std::unordered_map pips; std::unordered_map bels; + std::unordered_map groups; std::vector bel_ids, wire_ids, pip_ids; std::unordered_map> bel_ids_by_type; @@ -88,11 +99,17 @@ struct Arch : BaseCtx void addBelOutput(IdString bel, IdString name, IdString wire); void addBelInout(IdString bel, IdString name, IdString wire); + void addGroupBel(IdString group, IdString bel); + void addGroupWire(IdString group, IdString wire); + void addGroupPip(IdString group, IdString pip); + void addGroupGroup(IdString group, IdString grp); + void addDecalGraphic(DecalId decal, const GraphicElement &graphic); void setFrameDecal(DecalXY decalxy); void setWireDecal(WireId wire, DecalXY decalxy); void setPipDecal(PipId pip, DecalXY decalxy); void setBelDecal(BelId bel, DecalXY decalxy); + void setGroupDecal(GroupId group, DecalXY decalxy); // --------------------------------------------------------------- // Common Arch API. Every arch must provide the following methods. @@ -151,6 +168,14 @@ struct Arch : BaseCtx const std::vector &getPipsUphill(WireId wire) const; const std::vector &getWireAliases(WireId wire) const; + GroupId getGroupByName(IdString name) const; + IdString getGroupName(GroupId group) const; + std::vector getGroups() const; + const std::vector &getGroupBels(GroupId group) const; + const std::vector &getGroupWires(GroupId group) const; + const std::vector &getGroupPips(GroupId group) const; + const std::vector &getGroupGroups(GroupId group) const; + void estimatePosition(BelId bel, int &x, int &y, bool &gb) const; delay_t estimateDelay(WireId src, WireId dst) const; delay_t getDelayEpsilon() const { return 0.01; } @@ -166,6 +191,7 @@ struct Arch : BaseCtx DecalXY getBelDecal(BelId bel) const; DecalXY getWireDecal(WireId wire) const; DecalXY getPipDecal(PipId pip) const; + DecalXY getGroupDecal(GroupId group) const; bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, delay_t &delay) const; IdString getPortClock(const CellInfo *cell, IdString port) const; diff --git a/generic/archdefs.h b/generic/archdefs.h index 8e6dcb2f..9969014b 100644 --- a/generic/archdefs.h +++ b/generic/archdefs.h @@ -49,6 +49,7 @@ typedef IdString PortPin; typedef IdString BelId; typedef IdString WireId; typedef IdString PipId; +typedef IdString GroupId; typedef IdString DecalId; NEXTPNR_NAMESPACE_END diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index 0c70012f..7a188863 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -383,6 +383,16 @@ void FPGAViewWidget::paintGL() lineShader_.draw(pips, matrix); } + // Draw Groups. + auto groups = LineShaderData(0.0005f, QColor("#b000ba")); + if (ctx_) { + for (auto group : ctx_->getGroups()) { + for (auto &el : ctx_->getGroupGraphics(group)) + drawElement(groups, el); + } + lineShader_.draw(groups, matrix); + } + // Draw Frame Graphics. auto frames = LineShaderData(0.002f, QColor("#0066ba")); if (ctx_) { diff --git a/ice40/arch.cc b/ice40/arch.cc index 1e6b4569..26c3b003 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -369,6 +369,52 @@ std::string Arch::getBelPackagePin(BelId bel) const } return ""; } + +// ----------------------------------------------------------------------- + +GroupId Arch::getGroupByName(IdString name) const +{ + for (auto g : getGroups()) + if (getGroupName(g) == name) + return g; + return GroupId(); +} + +IdString Arch::getGroupName(GroupId group) const +{ + return IdString(); +} + +std::vector Arch::getGroups() const +{ + std::vector ret; + 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; +} + // ----------------------------------------------------------------------- void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const @@ -417,15 +463,15 @@ bool Arch::route() DecalXY Arch::getFrameDecal() const { DecalXY decalxy; - decalxy.decal.type = 'f'; + decalxy.decal.type = DecalId::TYPE_FRAME; return decalxy; } DecalXY Arch::getBelDecal(BelId bel) const { DecalXY decalxy; - decalxy.decal.type = 'b'; - decalxy.decal.z = bel.index; + decalxy.decal.type = DecalId::TYPE_BEL; + decalxy.decal.index = bel.index; return decalxy; } @@ -441,11 +487,17 @@ DecalXY Arch::getPipDecal(PipId pip) const return decalxy; }; +DecalXY Arch::getGroupDecal(GroupId group) const +{ + DecalXY decalxy; + return decalxy; +}; + std::vector Arch::getDecalGraphics(DecalId decal) const { std::vector ret; - if (decal.type == 'f') + if (decal.type == DecalId::TYPE_FRAME) { for (int x = 0; x <= chip_info->width; x++) for (int y = 0; y <= chip_info->height; y++) { @@ -458,10 +510,10 @@ std::vector Arch::getDecalGraphics(DecalId decal) const } } - if (decal.type == 'b') + if (decal.type == DecalId::TYPE_BEL) { BelId bel; - bel.index = decal.z; + bel.index = decal.index; auto bel_type = getBelType(bel); diff --git a/ice40/arch.h b/ice40/arch.h index 659139a6..96d0d209 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -634,6 +634,16 @@ struct Arch : BaseCtx // ------------------------------------------------- + GroupId getGroupByName(IdString name) const; + IdString getGroupName(GroupId group) const; + std::vector getGroups() const; + std::vector getGroupBels(GroupId group) const; + std::vector getGroupWires(GroupId group) const; + std::vector getGroupPips(GroupId group) const; + std::vector getGroupGroups(GroupId group) const; + + // ------------------------------------------------- + void estimatePosition(BelId bel, int &x, int &y, bool &gb) const; delay_t estimateDelay(WireId src, WireId dst) const; delay_t getDelayEpsilon() const { return 20; } @@ -654,6 +664,7 @@ struct Arch : BaseCtx DecalXY getBelDecal(BelId bel) const; DecalXY getWireDecal(WireId wire) const; DecalXY getPipDecal(PipId pip) const; + DecalXY getGroupDecal(GroupId group) const; // ------------------------------------------------- diff --git a/ice40/archdefs.h b/ice40/archdefs.h index 061e9b44..62c248c7 100644 --- a/ice40/archdefs.h +++ b/ice40/archdefs.h @@ -109,11 +109,42 @@ struct PipId bool operator!=(const PipId &other) const { return index != other.index; } }; +struct GroupId +{ + enum : int8_t { + TYPE_NONE, + TYPE_FRAME, + TYPE_MAIN_SW, + TYPE_LOCAL_SW, + TYPE_LC0_SW, + TYPE_LC1_SW, + TYPE_LC2_SW, + TYPE_LC3_SW, + TYPE_LC4_SW, + TYPE_LC5_SW, + TYPE_LC6_SW, + TYPE_LC7_SW + } type = TYPE_NONE; + int8_t x = 0, y = 0; + + bool operator==(const GroupId &other) const { return (type == other.type) && (x == other.x) && (y == other.y); } + bool operator!=(const GroupId &other) const { return (type != other.type) || (x != other.x) || (y == other.y); } +}; + struct DecalId { - char type = 0; // Bel/Wire/Pip/Frame (b/w/p/f) - uint8_t x = 0, y = 0; - uint32_t z = 0; + enum : int8_t { + TYPE_NONE, + TYPE_FRAME, + TYPE_BEL, + TYPE_WIRE, + TYPE_PIP, + TYPE_GROUP + } type = TYPE_NONE; + int32_t index = -1; + + bool operator==(const DecalId &other) const { return (type == other.type) && (index == other.index); } + bool operator!=(const DecalId &other) const { return (type != other.type) || (index != other.index); } }; NEXTPNR_NAMESPACE_END @@ -145,14 +176,23 @@ template <> struct hash : hash { }; +template <> struct hash +{ + std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX GroupId &group) const noexcept { + std::size_t seed = 0; + boost::hash_combine(seed, hash()(group.type)); + boost::hash_combine(seed, hash()(group.x)); + boost::hash_combine(seed, hash()(group.y)); + return seed; + } +}; + template <> struct hash { std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX DecalId &decal) const noexcept { std::size_t seed = 0; boost::hash_combine(seed, hash()(decal.type)); - boost::hash_combine(seed, hash()(decal.x)); - boost::hash_combine(seed, hash()(decal.y)); - boost::hash_combine(seed, hash()(decal.z)); + boost::hash_combine(seed, hash()(decal.index)); return seed; } };